]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge branch 'feature/funcwrite'
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 7 Apr 2017 07:38:57 +0000 (10:38 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 7 Apr 2017 07:38:57 +0000 (10:38 +0300)
334 files changed:
bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java
bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java
bundles/org.simantics.acorn/src/org/simantics/acorn/HeadState.java
bundles/org.simantics.acorn/src/org/simantics/acorn/HeadState1.java [new file with mode: 0644]
bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java
bundles/org.simantics.acorn/src/org/simantics/acorn/lru/LRU.java
bundles/org.simantics.acorn/src/org/simantics/acorn/lru/LRUObject.java
bundles/org.simantics.annotation.ui/scl/Simantics/Annotation2.scl
bundles/org.simantics.browsing.ui.model/src/org/simantics/browsing/ui/model/labeldecorators/ConstantLabelDecorationRule.java
bundles/org.simantics.browsing.ui.model/src/org/simantics/browsing/ui/model/labels/LabelContribution.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java
bundles/org.simantics.browsing.ui.swt/META-INF/MANIFEST.MF
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerFactory.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java
bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/GraphExplorer.java
bundles/org.simantics.charts/scl/Simantics/Chart.scl
bundles/org.simantics.charts/src/org/simantics/charts/Charts.java
bundles/org.simantics.charts/src/org/simantics/charts/TrendSupport.java
bundles/org.simantics.db.impl/META-INF/MANIFEST.MF
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/DatabaseIndexing.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsImpl.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/internal/IndexChangedWriter.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/SharedOntologyImportAdvisor.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigratedImportResult.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigrationStateImpl.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigrationStateKeys.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigrationUtils.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/PossibleVariableRepresents.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ConsistsOfProcess.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/DomainProcessor3.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/DomainProcessorState.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ExtendedUris.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ExternalDownloadBean.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ModelTransferableGraphSource.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Subgraphs.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/TGRepresentationUtils.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/XSupportImpl.java
bundles/org.simantics.db/src/org/simantics/db/service/XSupport.java
bundles/org.simantics.desktop.ui.ontology/graph.tg
bundles/org.simantics.diagram.ontology/graph.tg
bundles/org.simantics.diagram/META-INF/MANIFEST.MF
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/CompositeImage.java
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementFactory.java
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementHandler.java [new file with mode: 0644]
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java [new file with mode: 0644]
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java
bundles/org.simantics.diagram/src/org/simantics/diagram/elements/MonitorClass.java
bundles/org.simantics.diagram/src/org/simantics/diagram/elements/TextNode.java
bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java
bundles/org.simantics.diagram/src/org/simantics/diagram/flag/Splitter.java
bundles/org.simantics.diagram/src/org/simantics/diagram/handler/CopyPasteHandler.java
bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java
bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryComposite.java
bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java
bundles/org.simantics.document.base.ontology/graph.tg
bundles/org.simantics.document.ontology/META-INF/MANIFEST.MF
bundles/org.simantics.document.ontology/graph.tg
bundles/org.simantics.document.ontology/graph/Document.pgraph
bundles/org.simantics.document.ontology/src/org/simantics/document/DocumentResource.java
bundles/org.simantics.document.server.io/src/org/simantics/document/server/io/ITreeTableCell.java
bundles/org.simantics.document.server.io/src/org/simantics/document/server/io/JSONObjectUtils.java
bundles/org.simantics.document.server/scl/Document/All.scl
bundles/org.simantics.document.swt.ontology/graph.tg
bundles/org.simantics.document.ui.ontology/META-INF/MANIFEST.MF
bundles/org.simantics.document.ui.ontology/graph.tg
bundles/org.simantics.document.ui.ontology/graph/DocumentUI.pgraph
bundles/org.simantics.document.ui/META-INF/MANIFEST.MF
bundles/org.simantics.document.ui/scl/Simantics/Document.scl
bundles/org.simantics.document.ui/src/org/simantics/document/ui/actions/AddUrlDocument.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/actions/AddUrlDocumentWithDetail.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/actions/ExportDocumentFolder.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/actions/ImportDocumentFolder.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/actions/ImportDocumentWithDetail.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/function/All.java
bundles/org.simantics.document.ui/src/org/simantics/document/ui/wizard/FileDocumentImportWizard.java
bundles/org.simantics.document/META-INF/MANIFEST.MF
bundles/org.simantics.document/src/org/simantics/document/Activator.java
bundles/org.simantics.document/src/org/simantics/document/AddDocumentAction.java [new file with mode: 0644]
bundles/org.simantics.document/src/org/simantics/document/DocumentUtils.java
bundles/org.simantics.document/src/org/simantics/document/DocumentVersionUtils.java [new file with mode: 0644]
bundles/org.simantics.document/src/org/simantics/document/Exportable.java
bundles/org.simantics.document/src/org/simantics/document/FileDocumentUtil.java [new file with mode: 0644]
bundles/org.simantics.document/src/org/simantics/document/ImportDocument.java [new file with mode: 0644]
bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/ExportPdfFormat.java
bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/ExportPdfWriter.java
bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/FontMapping.java [new file with mode: 0644]
bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/PageNumbering.java [new file with mode: 0644]
bundles/org.simantics.fileimport.ui/META-INF/MANIFEST.MF
bundles/org.simantics.fileimport.ui/src/org/simantics/fileimport/ui/ImportFileHandler.java
bundles/org.simantics.fileimport/META-INF/MANIFEST.MF
bundles/org.simantics.fileimport/scl/Dropins/Core.scl
bundles/org.simantics.fileimport/src/org/simantics/fileimport/Activator.java
bundles/org.simantics.fileimport/src/org/simantics/fileimport/FileImportService.java
bundles/org.simantics.fileimport/src/org/simantics/fileimport/FileReferenceFileImport.java
bundles/org.simantics.fileimport/src/org/simantics/fileimport/LibraryFolderFileImport.java
bundles/org.simantics.fileimport/src/org/simantics/fileimport/scl/DropinsSCL.java
bundles/org.simantics.g2d/META-INF/MANIFEST.MF
bundles/org.simantics.g2d/src/org/simantics/g2d/chassis/AWTChassis.java
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java
bundles/org.simantics.g2d/src/org/simantics/g2d/element/ElementUtils.java
bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java
bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/MonitorClass.java [deleted file]
bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/RotatorHandler.java
bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/WheelClass.java
bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/resourceFiles/FilterCRWriter.java [new file with mode: 0644]
bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/resourceFiles/ResourceFile.java
bundles/org.simantics.graph.db/src/org/simantics/graph/db/CoreInitialization.java
bundles/org.simantics.graph.db/src/org/simantics/graph/db/ImportResult.java [new file with mode: 0644]
bundles/org.simantics.graph.db/src/org/simantics/graph/db/StreamingTransferableGraphImportProcess.java
bundles/org.simantics.graph.db/src/org/simantics/graph/db/TransferableGraphs.java
bundles/org.simantics.graph.db/src/org/simantics/graph/db/old/OldTransferableGraphs.java
bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java
bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java [new file with mode: 0644]
bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java
bundles/org.simantics.help.ontology/graph.tg
bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java
bundles/org.simantics.issues.common/src/org/simantics/issues/common/All.java
bundles/org.simantics.layer0/graph.tg
bundles/org.simantics.layer0/graph/Layer0.pgraph
bundles/org.simantics.layer0/graph/Layer0SCL.pgraph
bundles/org.simantics.layer0/src/org/simantics/layer0/Layer0.java
bundles/org.simantics.modeling.ontology/graph.tg
bundles/org.simantics.modeling.ontology/graph/Modeling.pgraph
bundles/org.simantics.modeling.ontology/graph/ModelingViewpoint.pgraph
bundles/org.simantics.modeling.ontology/src/org/simantics/modeling/ModelingResources.java
bundles/org.simantics.modeling.template2d.ui/scl/Simantics/DrawingTemplate.scl
bundles/org.simantics.modeling.ui/META-INF/MANIFEST.MF
bundles/org.simantics.modeling.ui/scl/Simantics/Library.scl
bundles/org.simantics.modeling.ui/scl/Simantics/Testing/ActionBrowseContext.scl
bundles/org.simantics.modeling.ui/scl/Simantics/Testing/BrowseContext.scl
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphs.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/ModeledActions.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/SymbolCodeDocumentProvider2.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/SymbolDropHandlerDocumentProvider.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/SliderClass.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/ConnectionPointNameStyle.java [new file with mode: 0644]
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/ContextualHelp.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser2/label/ConnectionRelationLabelDecorationRule.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/DiagramPrinter.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFDiagramExportWizard.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFExportPlan.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sharedontology/wizard/SharedOntologyImportWizard.java
bundles/org.simantics.modeling/META-INF/MANIFEST.MF
bundles/org.simantics.modeling/scl/Simantics/All.scl
bundles/org.simantics.modeling/scl/Simantics/Diagram.scl
bundles/org.simantics.modeling/scl/Simantics/DiagramMapping.scl
bundles/org.simantics.modeling/scl/Simantics/Flag.scl
bundles/org.simantics.modeling/scl/Simantics/Issue.scl
bundles/org.simantics.modeling/scl/Simantics/Model.scl
bundles/org.simantics.modeling/scl/Simantics/Rename.scl
bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl
bundles/org.simantics.modeling/scl/Simantics/Simulation.scl
bundles/org.simantics.modeling/scl/Simantics/Subscription.scl
bundles/org.simantics.modeling/scl/Simantics/UserComponent.scl
bundles/org.simantics.modeling/scl/Simantics/Workbench.scl [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ModelingUtils.java
bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java
bundles/org.simantics.modeling/src/org/simantics/modeling/internal/Activator.java
bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/CompileSCLMonitorRequest.java
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModule.java
bundles/org.simantics.platform.ui.ontology/graph.tg
bundles/org.simantics.project/src/org/simantics/project/ProjectFeatures.java
bundles/org.simantics.project/src/org/simantics/project/internal/ProjectFeatureRegistry.java
bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/request/AvailableProfiles.java [new file with mode: 0644]
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/request/RuntimeProfileActiveEntryResources.java
bundles/org.simantics.scenegraph.ui/src/org/simantics/scenegraph/ui/AttributeDialog.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DRenderingHints.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java [new file with mode: 0644]
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/UnboundedNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/NodeUtil.java
bundles/org.simantics.scl.compiler/META-INF/MANIFEST.MF
bundles/org.simantics.scl.compiler/OSGI-INF/org.simantics.scl.compiler.elaboration.java.LoggingModule.xml [new file with mode: 0644]
bundles/org.simantics.scl.compiler/build.properties
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/annotations/AnnotationUtils.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/JavaModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/LoggingModule.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/MinigraphModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/DummyJavaReferenceValidator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/JavaReferenceValidator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/JavaReferenceValidatorFactory.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/RuntimeJavaReferenceValidator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/SSAUtils.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ValueFromMethod.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/interpreted/ILambda.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserOptions.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLPostLexer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/InvalidModulePathException.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ModuleUtils.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/TextualModuleSource.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/BuiltinModuleSourceRepository.java
bundles/org.simantics.scl.db/scl/Simantics/DB.scl
bundles/org.simantics.scl.db/scl/Simantics/Variables.scl
bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSource.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/OsgiJavaReferenceValidatorFactory.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/generation/org/simantics/scl/runtime/generation/GenerateFunctions.java
bundles/org.simantics.scl.runtime/scl/Prelude.scl
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/Lists.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction1.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction2.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction3.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction4.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction5.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction6.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction7.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunction8.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/function/UnsaturatedFunctionN.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/reporting/SCLReportingWriter.java [new file with mode: 0644]
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor/completion/SCLTextEditorEnvironment.java
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/OpenDeclaration.java
bundles/org.simantics.selectionview.ontology/graph.tg
bundles/org.simantics.selectionview.ontology/graph/Selectionview.pgraph
bundles/org.simantics.selectionview.ui.ontology/graph.tg
bundles/org.simantics.selectionview.ui.ontology/graph/SelectionViewUi.pgraph
bundles/org.simantics.selectionview.ui.ontology/graph/scl/SCLMain.scl [new file with mode: 0644]
bundles/org.simantics.selectionview.ui.ontology/src/org/simantics/selectionview/ui/ontology/SelectionViewUIResources.java
bundles/org.simantics.simulation/META-INF/MANIFEST.MF
bundles/org.simantics.simulation/src/org/simantics/simulation/experiment/Experiment.java
bundles/org.simantics.simulation/src/org/simantics/simulation/experiment/ExperimentUtil.java
bundles/org.simantics.simulation/src/org/simantics/simulation/project/ExperimentManager.java
bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/TreeTableCell.java
bundles/org.simantics.spreadsheet.fileimport/src/org/simantics/spreadsheet/fileimport/ExcelFileImport.java
bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl
bundles/org.simantics.spreadsheet.ontology/graph.tg
bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/ModuleUpdateContext.java
bundles/org.simantics.ui/src/org/simantics/ui/contribution/OpenWithMenuContribution.java
bundles/org.simantics.ui/src/org/simantics/ui/contribution/OperationsMenuContribution.java
bundles/org.simantics.ui/src/org/simantics/ui/selection/WorkbenchSelectionUtils.java
bundles/org.simantics.ui/src/org/simantics/ui/workbench/editor/EditorRegistry.java
bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/BinaryCallback.java
bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/Callable.java
bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/TimingUtil.java
bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/UnaryFunction.java
bundles/org.simantics.utils.thread.swt/src/org/simantics/utils/threads/SWTThread.java
bundles/org.simantics.utils.thread/META-INF/MANIFEST.MF
bundles/org.simantics.utils.thread/src/org/simantics/utils/threads/Executors2.java [deleted file]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/dialogs/InfoDialog.java [new file with mode: 0644]
bundles/org.simantics.utils/src/org/simantics/utils/FileService.java
bundles/org.simantics.utils/src/org/simantics/utils/FileUtils.java
bundles/org.simantics.viewpoint.ontology/graph.tg
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ButtonLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CComboLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ComboLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CompositeLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ExplorerLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/LabelLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ScrolledCompositeLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TabFolderLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TextLoader.java.keep [deleted file]
bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TrackedTextLoader.java.keep [deleted file]
bundles/org.simantics.views.text.ontology/.classpath [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/.project [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/build.properties [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/graph.tg [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/graph/TextViews.pgraph [new file with mode: 0644]
bundles/org.simantics.views.text.ontology/src/.keep [new file with mode: 0644]
bundles/org.simantics.views.text/.classpath [new file with mode: 0644]
bundles/org.simantics.views.text/.project [new file with mode: 0644]
bundles/org.simantics.views.text/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.views.text/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.views.text/adapters.xml [new file with mode: 0644]
bundles/org.simantics.views.text/build.properties [new file with mode: 0644]
bundles/org.simantics.views.text/plugin.xml [new file with mode: 0644]
bundles/org.simantics.views.text/src/org/simantics/views/text/internal/Activator.java [new file with mode: 0644]
bundles/org.simantics.views.text/src/org/simantics/views/text/internal/SWTMarkupSourceViewer.java [new file with mode: 0644]
bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerConstants.java [new file with mode: 0644]
bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerUndoHandler.java [new file with mode: 0644]
bundles/org.simantics.wiki.ui/src/org/simantics/wiki/ui/editor/IExportable.java
bundles/org.simantics.workbench.ontology/graph.tg
bundles/org.simantics/src/org/simantics/OntologyImportAdvisor.java
bundles/org.simantics/src/org/simantics/SimanticsPlatform.java
bundles/pom.xml
features/org.simantics.desktop.product.feature/feature.xml
features/org.simantics.g2d.feature/feature.xml
features/org.simantics.sdk.feature/feature.xml
features/org.simantics.ui.workbench.feature/feature.xml
features/org.simantics.views.swt.feature/feature.xml
features/pom.xml
releng/doc/dump-mysql-db.sh [changed mode: 0644->0755]
releng/doc/dump-wikis.sh [changed mode: 0644->0755]
releng/doc/release.html
releng/doc/release.md
releng/org.simantics.desktop.rcp.product/.project [new file with mode: 0644]
releng/org.simantics.desktop.rcp.product/pom.xml [new file with mode: 0644]
releng/org.simantics.desktop.rcp.product/simantics-desktop.product [moved from bundles/org.simantics.desktop.product/simantics-desktop.product with 66% similarity]
releng/org.simantics.sdk.build.p2.site/pom.xml
releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target
releng/org.simantics.sdk.build.targetdefinition/simantics.target
releng/org.simantics.sdk.repository/pom.xml
releng/pom.xml
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/ClosureRecursion.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/FunctionIdentity.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Logger.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/SwitchSimplification.scl [new file with mode: 0644]

index 22629d4e64237ab63c6fc89a12f0754087254edb..40c5de37e8c1991e6e5ce846e2b90e7b651b6c5e 100644 (file)
@@ -2,9 +2,11 @@ package org.simantics.acorn;
 
 import java.io.IOException;
 import java.math.BigInteger;
+import java.nio.file.CopyOption;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -22,6 +24,7 @@ import org.simantics.acorn.lru.ClusterLRU;
 import org.simantics.acorn.lru.ClusterStreamChunk;
 import org.simantics.acorn.lru.FileInfo;
 import org.simantics.acorn.lru.LRU;
+import org.simantics.databoard.file.RuntimeIOException;
 import org.simantics.db.ClusterCreator;
 import org.simantics.db.Database.Session.ClusterIds;
 import org.simantics.db.Database.Session.ResourceSegment;
@@ -33,6 +36,7 @@ import org.simantics.db.impl.ClusterSupport;
 import org.simantics.db.procore.cluster.ClusterTraits;
 import org.simantics.db.service.ClusterSetsSupport;
 import org.simantics.db.service.ClusterUID;
+import org.simantics.utils.FileUtils;
 import org.simantics.utils.threads.logger.ITask;
 import org.simantics.utils.threads.logger.ThreadLogger;
 import org.slf4j.Logger;
@@ -134,6 +138,119 @@ public class ClusterManager {
        private AtomicBoolean safeToMakeSnapshot = new AtomicBoolean(true);
        private IllegalAcornStateException cause;
        
+       public synchronized void purge(ServiceLocator locator) throws IllegalAcornStateException {
+               
+           try {
+
+               // Schedule writing of all data to disk
+               refreshHeadState();
+               // Wait for files to be written
+               synchronizeWorkingDirectory();
+               
+               String currentDir = workingDirectory.getFileName().toString();
+               Path baseline = workingDirectory.resolveSibling(currentDir + "_baseline");
+               
+               Files.createDirectories(baseline);
+               
+               for(String clusterKey : state.clusters) {
+                       String[] parts1 = clusterKey.split("#");
+                       String[] parts = parts1[0].split("\\.");
+                       String readDirName = parts1[1];
+                       if(!readDirName.equals(currentDir)) {
+                               String fileName = parts[0] + "." + parts[1] + ".cluster";
+                               Path from = dbFolder.resolve(readDirName).resolve(fileName);
+                               Path to = baseline.resolve(fileName);
+                               System.err.println("purge copies " + from + "  => " + to);
+                               Files.copy(from, to, StandardCopyOption.COPY_ATTRIBUTES);
+                               long first = new BigInteger(parts[0], 16).longValue();
+                               long second = new BigInteger(parts[1], 16).longValue();
+                               ClusterUID uuid = ClusterUID.make(first, second);
+                               ClusterInfo info = clusterLRU.getWithoutMutex(uuid);
+                               info.moveTo(baseline);
+                       }
+               }
+               
+               for (String fileKey : state.files) {
+                       String[] parts = fileKey.split("#");
+                       String readDirName = parts[1];
+                       if(!readDirName.equals(currentDir)) {
+                               String fileName = parts[0] + ".extFile";
+                               Path from = dbFolder.resolve(readDirName).resolve(fileName);
+                               Path to = baseline.resolve(fileName);
+                               System.err.println("purge copies " + from + "  => " + to);
+                               Files.copy(from, to, StandardCopyOption.COPY_ATTRIBUTES);
+                               FileInfo info = fileLRU.getWithoutMutex(parts[0]);
+                               info.moveTo(baseline);
+                       }
+               }
+               
+               for (String fileKey : state.stream) {
+                       String[] parts = fileKey.split("#");
+                       String readDirName = parts[1];
+                       if(!readDirName.equals(currentDir)) {
+                               ClusterStreamChunk chunk = streamLRU.purge(parts[0]);
+                               System.err.println("purge removes " + chunk);
+                       }
+               }
+               
+               // Change sets
+               for (String fileKey : state.cs) {
+                       String[] parts = fileKey.split("#");
+                       String readDirName = parts[1];
+                       if(!readDirName.equals(currentDir)) {
+                               Long revisionId = Long.parseLong(parts[0]);
+                               ChangeSetInfo info = csLRU.purge(revisionId);
+                               System.err.println("purge removes " + info);
+                       }
+//                     Path readDir = dbFolder.resolve(parts[1]);
+//                     Long revisionId = Long.parseLong(parts[0]);
+//                     int offset = Integer.parseInt(parts[2]);
+//                     int length = Integer.parseInt(parts[3]);
+//                     ChangeSetInfo info = new ChangeSetInfo(csLRU, readDir, revisionId, offset, length);
+//                     csLRU.map(info);
+               }               
+               
+               state.tailChangeSetId = state.headChangeSetId;
+               
+               makeSnapshot(locator, true);
+               
+               Files.walk(dbFolder, 1).filter(Files::isDirectory).forEach(f -> tryPurgeDirectory(f));
+
+           } catch (IllegalAcornStateException e) {
+               notSafeToMakeSnapshot(e);
+               throw e;
+           } catch (IOException e) {
+               IllegalAcornStateException e1 = new IllegalAcornStateException(e);
+               notSafeToMakeSnapshot(e1);
+               throw e1;
+           } catch (AcornAccessVerificationException e) {
+               IllegalAcornStateException e1 = new IllegalAcornStateException(e);
+               notSafeToMakeSnapshot(e1);
+               throw e1;
+               }
+        
+       }
+       
+       void tryPurgeDirectory(Path f) {
+               
+               
+               System.err.println("purge deletes " + f);
+
+               String currentDir = f.getFileName().toString();
+               if(currentDir.endsWith("db"))
+                       return;
+
+               if(currentDir.endsWith("_baseline"))
+                       currentDir = currentDir.replace("_baseline", "");
+
+               int ordinal = Integer.parseInt(currentDir);
+               if(ordinal < mainState.headDir - 1) {
+                       System.err.println("purge deletes " + f);
+                       FileUtils.deleteDir(f.toFile());
+               }
+               
+       }
+
        public synchronized boolean makeSnapshot(ServiceLocator locator, boolean fullSave) throws IllegalAcornStateException {
            try {
            if (!safeToMakeSnapshot.get())
@@ -221,9 +338,13 @@ public class ClusterManager {
                csLRU.persist(state.cs);
        }
        
-       private void persistHeadState() throws IOException {
+       private void synchronizeWorkingDirectory() throws IOException {
                // Sync current working directory
                Files.walk(workingDirectory, 1).filter(Files::isRegularFile).forEach(FileIO::uncheckedSyncPath);
+       }
+       
+       private void persistHeadState() throws IOException {
+               synchronizeWorkingDirectory();
                state.save(workingDirectory);
                mainState.headDir++;
        }
@@ -583,4 +704,8 @@ public class ClusterManager {
         this.cause = t;
     }
 
+    public long getTailChangeSetId() {
+       return state.tailChangeSetId;
+    }
+    
 }
index 904427b6d617f6682c78547db1dde17a419dff48..dce477ebeae0fdf35d1db078acfd7e6e885ea825 100644 (file)
@@ -27,14 +27,13 @@ import org.simantics.acorn.exception.IllegalAcornStateException;
 import org.simantics.acorn.internal.ClusterChange;
 import org.simantics.acorn.internal.ClusterUpdateProcessorBase;
 import org.simantics.acorn.internal.UndoClusterUpdateProcessor;
+import org.simantics.acorn.lru.ClusterChangeSet.Entry;
 import org.simantics.acorn.lru.ClusterInfo;
 import org.simantics.acorn.lru.ClusterStreamChunk;
 import org.simantics.acorn.lru.ClusterUpdateOperation;
-import org.simantics.acorn.lru.ClusterChangeSet.Entry;
 import org.simantics.db.ClusterCreator;
 import org.simantics.db.Database;
 import org.simantics.db.ServiceLocator;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.SDBException;
 import org.simantics.db.server.ProCoreException;
@@ -43,11 +42,14 @@ import org.simantics.db.service.ClusterUID;
 import org.simantics.db.service.LifecycleSupport;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.logging.TimeLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.TLongObjectHashMap;
 
 public class GraphClientImpl2 implements Database.Session {
-       
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GraphClientImpl2.class);
        public static final boolean DEBUG = false;
 
        public final ClusterManager clusters;
@@ -124,10 +126,10 @@ public class GraphClientImpl2 implements Database.Session {
                                                mainProgram.mutex.release();
                                        }
                                } catch (IllegalAcornStateException | ProCoreException e) {
-                                       Logger.defaultLogError("Snapshotting failed", e);
+                                       LOGGER.error("Snapshotting failed", e);
                                        unexpectedClose = true;
                                } catch (InterruptedException e) {
-                                       Logger.defaultLogError("Snapshotting interrupted", e);
+                                   LOGGER.error("Snapshotting interrupted", e);
                                } finally {
                                        try {
                                                if(tr != null)
@@ -137,11 +139,11 @@ public class GraphClientImpl2 implements Database.Session {
                            try {
                                support.close();
                            } catch (DatabaseException e1) {
-                               Logger.defaultLogError("Failed to close database as a safety measure due to failed snapshotting", e1);
+                               LOGGER.error("Failed to close database as a safety measure due to failed snapshotting", e1);
                            }
                                                }
                                        } catch (ProCoreException e) {
-                                               Logger.defaultLogError("Failed to end snapshotting write transaction", e);
+                                           LOGGER.error("Failed to end snapshotting write transaction", e);
                                        }
                                }
                        }
@@ -184,7 +186,7 @@ public class GraphClientImpl2 implements Database.Session {
        
        @Override
        public void close() throws ProCoreException {
-           System.err.println("Closing " + this + " and mainProgram " + mainProgram);
+           LOGGER.info("Closing " + this + " and mainProgram " + mainProgram);
                if(!closed && !isClosing) {
                    isClosing = true;
                        try {
@@ -249,7 +251,7 @@ public class GraphClientImpl2 implements Database.Session {
                        clusters.state.headChangeSetId++;
                        return clusters.state.headChangeSetId;
                } catch (SDBException e) {
-                       Logger.defaultLogError("Failed to undo cancelled transaction", e);
+                   LOGGER.error("Failed to undo cancelled transaction", e);
                        throw new ProCoreException(e);
                }
        }
@@ -725,29 +727,67 @@ public class GraphClientImpl2 implements Database.Session {
     public boolean rolledback() {
         return clusters.rolledback();
     }
+    
+    public void purge() throws IllegalAcornStateException {
+        clusters.purge(locator);
+    }
 
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       ////////////////////////
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
+    public void purgeDatabase() {
+       
+           if (isClosing || unexpectedClose)
+               return;
+           
+               saver.execute(new Runnable() {
+
+                       @Override
+                       public void run() {
+                               Transaction tr = null;
+                               try {
+                                       // First take a write transaction
+                                       tr = askWriteTransaction(-1);
+                                       // Then make sure that MainProgram is idling
+                                       mainProgram.mutex.acquire();
+                                       try {
+                                               synchronized(mainProgram) {
+                                                       if(mainProgram.operations.isEmpty()) {
+                                                               purge();
+                                                       } else {
+                                                               // MainProgram is becoming busy again - delay snapshotting
+                                                               return;
+                                                       }
+                                               }
+                                       } finally {
+                                               mainProgram.mutex.release();
+                                       }
+                               } catch (IllegalAcornStateException | ProCoreException e) {
+                                   LOGGER.error("Purge failed", e);
+                                       unexpectedClose = true;
+                               } catch (InterruptedException e) {
+                                   LOGGER.error("Purge interrupted", e);
+                               } finally {
+                                       try {
+                                               if(tr != null)
+                                                       endTransaction(tr.getTransactionId());
+                                               if (unexpectedClose) {
+                                               LifecycleSupport support = getServiceLocator().getService(LifecycleSupport.class);
+                           try {
+                               support.close();
+                           } catch (DatabaseException e1) {
+                               LOGGER.error("Failed to close database as a safety measure due to failed purge", e1);
+                           }
+                                               }
+                                       } catch (ProCoreException e) {
+                                           LOGGER.error("Failed to end purge write transaction", e);
+                                       }
+                               }
+                       }
+               });
+       
+    }
+    
+    public long getTailChangeSetId() {
+       return clusters.getTailChangeSetId();
+    }
+    
 }
 
index dd8703c1fc689e0ed0bbfc1968e6730913d74750..fd38bc98542052bbdb2e762c65d49a4cad4f3585 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Arrays;
 
 import org.simantics.acorn.exception.InvalidHeadStateException;
 import org.simantics.databoard.Bindings;
+import org.simantics.databoard.adapter.AdapterConstructionException;
 import org.simantics.databoard.binding.mutable.MutableVariant;
 import org.simantics.databoard.serialization.Serializer;
 import org.simantics.databoard.util.binary.BinaryMemory;
@@ -31,6 +32,8 @@ public class HeadState {
     public ArrayList<String> cs = new ArrayList<>();
 //    public ArrayList<String> ccs = new ArrayList<String>();
 
+    public long tailChangeSetId = 1;
+
     public static HeadState load(Path directory) throws InvalidHeadStateException {
         Path f = directory.resolve(HEAD_STATE);
         
@@ -51,6 +54,11 @@ public class HeadState {
                 return object;
             }
         } catch (IOException i) {
+               Throwable cause = i.getCause();
+               if(cause instanceof AdapterConstructionException) {
+                       HeadState1 old = HeadState1.load(directory);
+                       return old.migrate();
+               }
             return new HeadState();
 //            throw new InvalidHeadStateException(i);
         } catch (NoSuchAlgorithmException e) {
diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/HeadState1.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/HeadState1.java
new file mode 100644 (file)
index 0000000..d58a286
--- /dev/null
@@ -0,0 +1,117 @@
+package org.simantics.acorn;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.simantics.acorn.exception.InvalidHeadStateException;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.mutable.MutableVariant;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.util.binary.BinaryMemory;
+
+public class HeadState1 {
+
+    public static final String HEAD_STATE = "head.state";
+    public static final String SHA_1 = "SHA-1";
+    
+    public int headChangeSetId = 0;
+    public long transactionId = 1;
+    public long reservedIds = 3;
+
+    public ArrayList<String> clusters = new ArrayList<>();
+    public ArrayList<String> files = new ArrayList<>();
+    public ArrayList<String> stream = new ArrayList<>();
+    public ArrayList<String> cs = new ArrayList<>();
+    
+    public HeadState migrate() {
+       HeadState state = new HeadState();
+       state.headChangeSetId = headChangeSetId;
+       state.transactionId = transactionId;
+       state.reservedIds = reservedIds;
+       state.clusters = clusters;
+       state.files = files;
+       state.stream = stream;
+       state.cs = cs;
+       return state;
+    }
+
+    public static HeadState1 load(Path directory) throws InvalidHeadStateException {
+        Path f = directory.resolve(HEAD_STATE);
+        
+        try {
+            byte[] bytes = Files.readAllBytes(f);
+            MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
+            int digestLength = sha1.getDigestLength();
+            
+            sha1.update(bytes, digestLength, bytes.length - digestLength);
+            byte[] newChecksum = sha1.digest();
+            if (!Arrays.equals(newChecksum, Arrays.copyOfRange(bytes, 0, digestLength))) {
+                throw new InvalidHeadStateException(
+                        "Checksum " + Arrays.toString(newChecksum) + " does not match excpected "
+                                + Arrays.toString(Arrays.copyOfRange(bytes, 0, digestLength)) + " for " + f.toAbsolutePath());
+            }
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes, digestLength, bytes.length - digestLength)) {
+                HeadState1 object = (HeadState1) org.simantics.databoard.Files.readFile(bais, Bindings.getBindingUnchecked(HeadState1.class));
+                return object;
+            }
+        } catch (IOException i) {
+            return new HeadState1();
+        } catch (NoSuchAlgorithmException e) {
+            throw new Error("SHA-1 Algorithm not found", e);
+        } catch (Throwable t) {
+            throw new InvalidHeadStateException(t);
+        }
+    }
+    
+    public void save(Path directory) throws IOException {
+        Path f = directory.resolve(HEAD_STATE);
+        try {
+            BinaryMemory rf = new BinaryMemory(4096);
+            try {
+                MutableVariant v = new MutableVariant(Bindings.getBindingUnchecked(HeadState1.class), this);
+                Serializer s = Bindings.getSerializerUnchecked( Bindings.VARIANT );
+                s.serialize(rf, v);
+            } finally {
+                rf.close();
+            }
+            
+            byte[] bytes = rf.toByteBuffer().array();
+            
+            MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
+            sha1.update(bytes);
+            byte[] checksum = sha1.digest();
+            
+            try (OutputStream out = Files.newOutputStream(f)) {
+                out.write(checksum);
+                out.write(bytes);
+            }
+            FileIO.syncPath(f);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Error("SHA-1 digest not found, should not happen", e);
+        }
+    }
+
+    public static void validateHeadStateIntegrity(Path headState) throws InvalidHeadStateException, IOException {
+        try {
+            byte[] bytes = Files.readAllBytes(headState);
+            MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
+            int digestLength = sha1.getDigestLength();
+            sha1.update(bytes, digestLength, bytes.length - digestLength);
+            byte[] newChecksum = sha1.digest();
+            if (!Arrays.equals(newChecksum, Arrays.copyOfRange(bytes, 0, digestLength))) {
+                throw new InvalidHeadStateException(
+                        "Checksum " + Arrays.toString(newChecksum) + " does not match excpected "
+                                + Arrays.toString(Arrays.copyOfRange(bytes, 0, digestLength)) + " for " + headState.toAbsolutePath());
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new Error("SHA-1 digest not found, should not happen", e);
+        }
+    }
+}
index be505c6039712e322ce80ffa653c1b4c6babac13..1025cc6a5dac0a2e6d5b940b1ad0d17ba971fa00 100644 (file)
@@ -19,7 +19,10 @@ import org.simantics.db.Database;
 import org.simantics.db.DatabaseUserAgent;
 import org.simantics.db.ServiceLocator;
 import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.SDBException;
+import org.simantics.db.server.DatabaseStartException;
 import org.simantics.db.server.ProCoreException;
+import org.simantics.db.server.internal.InternalException;
 
 /**
  * @author Tuukka Lehtonen
@@ -27,6 +30,8 @@ import org.simantics.db.server.ProCoreException;
 public class AcornDatabase implements Database {
 
     private final Path folder;
+    
+    private GraphClientImpl2 currentClient;
 
     private DatabaseUserAgent userAgent;
 
@@ -190,22 +195,22 @@ public class AcornDatabase implements Database {
 
     @Override
     public void purgeDatabase() throws ProCoreException {
-        // TODO: implement
-        throw new UnsupportedOperationException();
+       if(currentClient == null) throw new IllegalStateException("No current session.");
+       currentClient.purgeDatabase();
     }
 
     @Override
     public long serverGetTailChangeSetId() throws ProCoreException {
-        // "We have it all"
-        // But after purging we don't so beware.
-        // TODO: beware for purge
-        return 1;
+       if(currentClient == null) throw new IllegalStateException("No current session.");
+       return currentClient.getTailChangeSetId();
     }
 
     @Override
     public Session newSession(ServiceLocator locator) throws ProCoreException {
         try {
-            return new GraphClientImpl2(this, folder, locator);
+               if(currentClient != null) throw new DatabaseStartException(folder.toFile(), "A session is already running. Only one session is supported.");
+               currentClient = new GraphClientImpl2(this, folder, locator); 
+            return currentClient;
         } catch (IOException e) {
             throw new ProCoreException(e);
         }
index 323d66d3df12ea34d2d429293801eeacfc95a23b..80fec7032940ac3e7a6a1abbebb02325880a8bfc 100644 (file)
@@ -16,16 +16,19 @@ import org.simantics.acorn.ClusterManager;
 import org.simantics.acorn.GraphClientImpl2;
 import org.simantics.acorn.exception.AcornAccessVerificationException;
 import org.simantics.acorn.exception.IllegalAcornStateException;
-import org.simantics.db.common.utils.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /*
  * The order rule of synchronization for LRU and LRUObject is:
- *   Â§ Always lock LRUObject first!
+ *   ï¿½ Always lock LRUObject first!
  * 
  */
 
 public class LRU<MapKey,MapValue extends LRUObject<MapKey, MapValue>> {
-       
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(LRU.class); 
+    
        public static boolean VERIFY = true;
 
        final private long swapTime = 5L*1000000000L;
@@ -148,6 +151,12 @@ public class LRU<MapKey,MapValue extends LRUObject<MapKey, MapValue>> {
                }
        }
 
+       
+       
+       public MapValue purge(MapKey id) {
+               return map.remove(id);
+       }
+
        public MapValue get(MapKey key) throws AcornAccessVerificationException {
                
                if(VERIFY) verifyAccess();
@@ -513,7 +522,7 @@ public class LRU<MapKey,MapValue extends LRUObject<MapKey, MapValue>> {
                            manager.notSafeToMakeSnapshot(new IllegalAcornStateException(t));
                        }
                        t.printStackTrace();
-                       Logger.defaultLogError(t);
+                       LOGGER.error("Exception happened in WriteRunnable.run", t);
                    }
                }
 
@@ -553,7 +562,7 @@ public class LRU<MapKey,MapValue extends LRUObject<MapKey, MapValue>> {
                         runWithMutex();
                         done = true;
                     } else {
-                        System.err.println("Retry mutex acquire");
+                        LOGGER.warn("Retry mutex acquire");
                         gotMutex = impl.tryAcquireMutex();
                     }
 
index 3194d591e0b37e8712e8cabf3cc1afcb9549a754..508c951067dedc3df895d938b3a0e84f9dda771c 100644 (file)
@@ -243,5 +243,9 @@ public abstract class LRUObject<MapKey, MapValue extends LRUObject<MapKey, MapVa
                if(VERIFY) verifyAccess();
                return readDirectory;
        }
+
+       public void moveTo(Path path) {
+               readDirectory = path;
+       }
        
 }
\ No newline at end of file
index cd3f851cbf8afd65de822d935d20ad179424d47f..b06a8bdd41d8f810fe8448bae5935e79e037063b 100644 (file)
@@ -104,13 +104,13 @@ getPossibleAnnotationType model name = do
     all = searchByType model ANNO.AnnotationType
     named = filter (\x -> (getAnnotationNameFromType x) == name) all 
     if ((length named) == 1)
-     then Just (fromResource $ named!0) 
+     then Just (named!0) 
      else Nothing
     
 setAnnotationPropertyValue :: AnnotationPropertyRelation -> Resource -> String -> String -> <WriteGraph> ()
 setAnnotationPropertyValue annotation resource property newValue = do
     resourceUri = uriOf resource
-    annotationName = DB.nameOf (toResource annotation)
+    annotationName = DB.nameOf annotation
     completeUri = resourceUri + "#" + annotationName + "#" + property + "#HasDisplayValue"
     propertyVariable = variable completeUri
     setValue propertyVariable newValue
index 3bb2db942095c6a34390377a2d69488c57d2c094..494c0a8198b88685025e84c7e2abd4829e91d94f 100644 (file)
@@ -13,7 +13,9 @@ package org.simantics.browsing.ui.model.labeldecorators;
 
 import org.eclipse.jface.resource.ColorDescriptor;
 import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.RGB;
 import org.simantics.browsing.ui.content.LabelDecorator;
 import org.simantics.databoard.Bindings;
@@ -133,6 +135,7 @@ public class ConstantLabelDecorationRule extends AbstractLabelDecorator implemen
             return font;
         else {
             FontDescriptor desc = (FontDescriptor)font;
+            if(desc == null) desc = FontDescriptor.createFrom(JFaceResources.getDialogFont().getFontData());
             return (Font)desc.withStyle(style);
         }
     }
index e8a7b62227db8d40ab51bb5ea978af1bb20dc322..25f0d054d5b55670c934940c993048fbcb728c79 100644 (file)
@@ -24,6 +24,7 @@ import org.simantics.browsing.ui.model.tests.Test;
 import org.simantics.browsing.ui.model.visuals.VisualsContribution;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.exception.PendingVariableException;
 
 /**
  * Produces labels for nodes of given node type.
@@ -31,7 +32,7 @@ import org.simantics.db.exception.DatabaseException;
  */
 public class LabelContribution extends VisualsContribution {
     LabelRule labelRule;
-    
+
     public LabelContribution(NodeType nodeType, Test test, LabelRule labelRule, double priority) throws InvalidContribution {
         super(nodeType, test, priority);
         if(!labelRule.isCompatible(
@@ -40,7 +41,7 @@ public class LabelContribution extends VisualsContribution {
             throw new InvalidContribution("Label rule is not compatible with the content type.");
         this.labelRule = labelRule;
     }
-       
+
     /**
      * Returns a label for the node or null, if contribution is
      * not suitable for the input.
@@ -48,15 +49,15 @@ public class LabelContribution extends VisualsContribution {
     public Map<String, String> getLabel(ReadGraph graph, NodeContext context) {
         Object content = context.getConstant(BuiltinKeys.INPUT);
         try {
-            if(test == null || test.test(graph, content))            
+            if(test == null || test.test(graph, content))
                 return labelRule.getLabel(graph, content);
             else
                 return null;
+        } catch(PendingVariableException e) {
+            return Collections.singletonMap(ColumnKeys.SINGLE, "");
         } catch(DatabaseException e) {
             ErrorLogger.defaultLogError(e);
-               //Logger.defaultLogError(e);
-            // TODO reconsider
             return Collections.singletonMap(ColumnKeys.SINGLE, "");
         }
-    }    
+    }
 }
index cc978e7e8b6ce599957ff6fbb859c76ec96a0d96..3bb05553dc7456e073d52b44e526688c2beffdc0 100644 (file)
@@ -19,6 +19,7 @@ import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.Assert;
@@ -89,7 +90,6 @@ import org.eclipse.nebula.widgets.nattable.painter.NatTableBorderOverlayPainter;
 import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
-import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand;
 import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
 import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
@@ -190,7 +190,6 @@ import org.simantics.browsing.ui.swt.ViewerCellReference;
 import org.simantics.browsing.ui.swt.ViewerRowReference;
 import org.simantics.browsing.ui.swt.internal.Threads;
 import org.simantics.db.layer0.SelectionHints;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.MapList;
 import org.simantics.utils.datastructures.disposable.AbstractDisposable;
 import org.simantics.utils.datastructures.hints.IHintContext;
@@ -297,10 +296,10 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     private boolean expand;
     private boolean verticalBarVisible = false;
     
-    private BinaryFunction<Object[], GraphExplorer, Object[]>  selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
+    private BiFunction<GraphExplorer, Object[], Object[]>  selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
 
         @Override
-        public Object[] call(GraphExplorer explorer, Object[] objects) {
+        public Object[] apply(GraphExplorer explorer, Object[] objects) {
             Object[] result = new Object[objects.length];
             for (int i = 0; i < objects.length; i++) {
                 IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN);
@@ -846,7 +845,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     }
     
     protected Object[] transformSelection(Object[] objects) {
-        return selectionTransformation.call(this, objects);
+        return selectionTransformation.apply(this, objects);
     }
     
     protected static Object[] filter(SelectionFilter filter, NodeContext[] contexts) {
@@ -859,7 +858,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
 
        @Override
        public void setSelectionTransformation(
-                       BinaryFunction<Object[], GraphExplorer, Object[]> f) {
+                       BiFunction<GraphExplorer, Object[], Object[]> f) {
                this.selectionTransformation = f;
        }
        
index 9869cab3d663ac1d4049c13fb2ac6bb6ba337600..37466aedaec815dd3ae618a0c57592d90bfedc92 100644 (file)
@@ -16,7 +16,8 @@ Require-Bundle: org.simantics.utils.thread.swt;bundle-version="1.0.0",
  com.lowagie.text;bundle-version="2.1.5",
  org.simantics.scl.ui.editor;bundle-version="0.1.3";visibility:=reexport,
  org.simantics.scl.compiler.dummy;bundle-version="0.1.3",
- org.eclipse.e4.core.contexts;bundle-version="1.4.0"
+ org.eclipse.e4.core.contexts;bundle-version="1.4.0",
+ org.slf4j.api;bundle-version="1.7.20"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.simantics.browsing.ui.swt,
  org.simantics.browsing.ui.swt.contentassist,
index de421565951a2a3b025856676954f469c897e534..b99962bf00d579c6ceb3cf8e0d4eea39a85abe73 100644 (file)
@@ -12,6 +12,7 @@
 package org.simantics.browsing.ui.swt;
 
 import java.lang.reflect.Method;
+import java.util.function.BiFunction;
 
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.swt.SWT;
@@ -34,7 +35,6 @@ import org.simantics.db.layer0.SelectionHints;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.simulation.ontology.SimulationResource;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.hints.IHintContext;
 import org.simantics.utils.ui.ExceptionUtils;
 
@@ -50,7 +50,7 @@ public class GraphExplorerFactory {
 
     private IServiceLocator        serviceLocator;
 
-    private BinaryFunction<Object[], GraphExplorer, Object[]>  selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
+    private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
 
        private Resource getModel(final Object object) {
                if(object instanceof NodeContext) {
@@ -90,9 +90,8 @@ public class GraphExplorerFactory {
                return null;
        }
        
-       
         @Override
-        public Object[] call(GraphExplorer explorer, Object[] objects) {
+        public Object[] apply(GraphExplorer explorer, Object[] objects) {
             Object[] result = new Object[objects.length];
             for (int i = 0; i < objects.length; i++) {
                 IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN);
@@ -120,7 +119,7 @@ public class GraphExplorerFactory {
         return this;
     }
 
-    public GraphExplorerFactory selectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> transformation) {
+    public GraphExplorerFactory selectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> transformation) {
         this.selectionTransformation = transformation;
         return this;
     }
@@ -194,7 +193,8 @@ public class GraphExplorerFactory {
         //GraphExplorerImpl2 explorer = new GraphExplorerImpl2(parent, style);
        try {
                Bundle bundle = Platform.getBundle("org.simantics.browsing.ui.nattable");
-               Class<GraphExplorer> clazz = (Class<GraphExplorer>)bundle.loadClass("org.simantics.browsing.ui.nattable.NatTableGraphExplorer");
+               @SuppressWarnings("unchecked")
+                       Class<GraphExplorer> clazz = (Class<GraphExplorer>)bundle.loadClass("org.simantics.browsing.ui.nattable.NatTableGraphExplorer");
                //Class<GraphExplorer> clazz = (Class<GraphExplorer>)bundle.getClass().getClassLoader().loadClass("org.simantics.browsing.ui.nattable.NatTableGraphExplorer");
                GraphExplorer explorer = clazz.getConstructor(Composite.class, int.class).newInstance(parent,style);
                explorer.setSelectionDataResolver(selectionDataResolver);
index 62b284858cd9893383719e5ec7b89632437335f9..0e45f86ca4843fe53233ecec6217a07026ee4954 100644 (file)
@@ -31,6 +31,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.Assert;
@@ -161,7 +162,6 @@ import org.simantics.browsing.ui.swt.internal.Threads;
 import org.simantics.db.layer0.SelectionHints;
 import org.simantics.utils.ObjectUtils;
 import org.simantics.utils.datastructures.BijectionMap;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.disposable.AbstractDisposable;
 import org.simantics.utils.datastructures.hints.IHintContext;
 import org.simantics.utils.threads.IThreadWorkQueue;
@@ -544,10 +544,10 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
     protected BasePostSelectionProvider          selectionProvider        = new BasePostSelectionProvider();
     protected SelectionDataResolver              selectionDataResolver;
     protected SelectionFilter                    selectionFilter;
-    protected BinaryFunction<Object[], GraphExplorer, Object[]>  selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
+    protected BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
 
         @Override
-        public Object[] call(GraphExplorer explorer, Object[] objects) {
+        public Object[] apply(GraphExplorer explorer, Object[] objects) {
             Object[] result = new Object[objects.length];
             for (int i = 0; i < objects.length; i++) {
                 IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN);
@@ -1812,7 +1812,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
     }
 
     @Override
-    public void setSelectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> f) {
+    public void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> f) {
         this.selectionTransformation = f;
     }
 
@@ -3168,7 +3168,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
     }
 
     protected Object[] transformSelection(Object[] objects) {
-        return selectionTransformation.call(this, objects);
+        return selectionTransformation.apply(this, objects);
     }
 
     protected static Object[] filter(SelectionFilter filter, NodeContext[] contexts) {
index 79bd35b872b2991a05537aedede0b62aa50a6561..928bed03facc844eea8ef2603307e0a2c988f965 100644 (file)
@@ -30,6 +30,7 @@ import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.Assert;
@@ -164,7 +165,6 @@ import org.simantics.browsing.ui.swt.internal.Threads;
 import org.simantics.db.layer0.SelectionHints;
 import org.simantics.ui.SimanticsUI;
 import org.simantics.utils.datastructures.BijectionMap;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.MapList;
 import org.simantics.utils.datastructures.disposable.AbstractDisposable;
 import org.simantics.utils.datastructures.hints.IHintContext;
@@ -251,10 +251,10 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
     private boolean expand;
     private boolean verticalBarVisible = false;
     
-    private BinaryFunction<Object[], GraphExplorer, Object[]>  selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
+    private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
 
         @Override
-        public Object[] call(GraphExplorer explorer, Object[] objects) {
+        public Object[] apply(GraphExplorer explorer, Object[] objects) {
             Object[] result = new Object[objects.length];
             for (int i = 0; i < objects.length; i++) {
                 IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN);
@@ -885,7 +885,7 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
     }
     
     protected Object[] transformSelection(Object[] objects) {
-        return selectionTransformation.call(this, objects);
+        return selectionTransformation.apply(this, objects);
     }
     
     protected static Object[] filter(SelectionFilter filter, NodeContext[] contexts) {
@@ -898,7 +898,7 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
 
        @Override
        public void setSelectionTransformation(
-                       BinaryFunction<Object[], GraphExplorer, Object[]> f) {
+                       BiFunction<GraphExplorer, Object[], Object[]> f) {
                this.selectionTransformation = f;
        }
        
index 4b5a48e14acdb79f0cee6f1e42a798b2b142312b..f583d7e7f1df374f0466232cf40d786a4b14cf2b 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.IAdaptable;
@@ -102,12 +103,11 @@ import org.simantics.db.AsyncReadGraph;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
-import org.simantics.db.common.request.ResourceRead;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.SelectionHints;
+import org.simantics.db.layer0.request.PossibleVariable;
+import org.simantics.db.layer0.request.PossibleVariableRepresents;
 import org.simantics.db.layer0.variable.Variable;
-import org.simantics.db.layer0.variable.Variables;
 import org.simantics.db.management.ISessionContext;
 import org.simantics.db.management.ISessionContextChangedListener;
 import org.simantics.db.management.ISessionContextProvider;
@@ -126,7 +126,6 @@ import org.simantics.ui.selection.WorkbenchSelectionContentType;
 import org.simantics.ui.selection.WorkbenchSelectionElement;
 import org.simantics.ui.selection.WorkbenchSelectionUtils;
 import org.simantics.utils.ObjectUtils;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.Function;
 import org.simantics.utils.datastructures.disposable.DisposeState;
 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
@@ -135,10 +134,14 @@ import org.simantics.utils.datastructures.hints.IHintContext.Key;
 import org.simantics.utils.datastructures.hints.IHintListener;
 import org.simantics.utils.datastructures.hints.IHintObservable;
 import org.simantics.utils.datastructures.hints.IHintTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(GraphExplorerComposite.class);
+
     protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
     protected UserSelectedViewpointFactoryQueryProcessor  userSelectedViewpointFactoryQueryProcessor;
     protected FilterSelectionRequestQueryProcessor        filterSelectionRequestQueryProcessor;
@@ -248,39 +251,41 @@ public class GraphExplorerComposite extends Composite implements Widget, IAdapta
         @SuppressWarnings("unchecked")
         @Override
         public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
-
-            if(wse != null) {
+            if (wse != null) {
                 T result = wse.getContent(contentType);
-                if(result != null) return result;
+                if (result != null)
+                    return result;
             }
-            
-            if(contentType instanceof AnyResource) return (T)resource;
-            else if(contentType instanceof AnyVariable) {
-                AnyVariable type = (AnyVariable)contentType;
+
+            if (contentType instanceof AnyResource) {
+                if (resource != null)
+                    return (T) resource;
+                if (variable == null)
+                    return null;
+                try {
+                    return (T) ((AnyResource) contentType).processor.syncRequest(new PossibleVariableRepresents(variable));
+                } catch (DatabaseException e) {
+                    LOGGER.error("Unexpected error occurred while resolving Resource from Variable " + variable, e);
+                }
+            }
+            else if (contentType instanceof AnyVariable) {
+                if (variable != null)
+                    return (T) variable;
+                if (resource == null)
+                    return null;
                 try {
-                       
-                       if(variable != null) return (T)variable;
-                       
-                       if(resource == null) return null;
-                       
-                    return (T) type.processor.sync(new ResourceRead<Variable>(resource) {
-                        @Override
-                        public Variable perform(ReadGraph graph) throws DatabaseException {
-                            return Variables.getPossibleVariable(graph, resource);
-                        }
-                        
-                    });
+                    return (T) ((AnyVariable) contentType).processor.syncRequest(new PossibleVariable(resource));
                 } catch (DatabaseException e) {
-                    Logger.defaultLogError(e);
+                    LOGGER.error("Unexpected error occurred while resolving Variable from Resource " + resource, e);
                 }
             } else if (contentType instanceof ExplorerInputContentType) {
-               return (T)input;
+                return (T) input;
             } else if (contentType instanceof ExplorerColumnContentType) {
-               return (T)explorerState.getActiveColumn();
+                return (T) explorerState.getActiveColumn();
             }
             return null;
         }
-        
+
         @SuppressWarnings("rawtypes")
         @Override
         public Object getAdapter(Class adapter) {
@@ -297,12 +302,12 @@ public class GraphExplorerComposite extends Composite implements Widget, IAdapta
         }
 
     }
-    private BinaryFunction<Object[], GraphExplorer, Object[]> selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
+    private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
 
        private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };
        
         @Override
-        public Object[] call(GraphExplorer explorer, Object[] objects) {
+        public Object[] apply(GraphExplorer explorer, Object[] objects) {
             Object[] result = new Object[objects.length];
             for (int i = 0; i < objects.length; i++) {
                SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);
@@ -723,7 +728,7 @@ public class GraphExplorerComposite extends Composite implements Widget, IAdapta
                                                        event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());
                                                } catch (DatabaseException e) {
                                                        event.data = "{ type:\"Exception\" }";
-                                                       Logger.defaultLogError(e);
+                                                       LOGGER.error("Failed to get current selection as JSON.", e);
                                                }
                                        } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
                                                ls.dragSetData(event);
@@ -863,7 +868,7 @@ public class GraphExplorerComposite extends Composite implements Widget, IAdapta
        this.filterAreaSource = provider;
     }
 
-    public void setSelectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> transformation) {
+    public void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> transformation) {
         this.selectionTransformation = transformation;
         if(explorer != null) explorer.setSelectionTransformation(transformation);
     }
index 0bc3e02158018f79da1b9c24e2b4229fe1644a56..0745d1d81cae3e2cd866cab0aa4210c85b9e0fe2 100644 (file)
@@ -14,6 +14,7 @@ package org.simantics.browsing.ui;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.IAdaptable;
@@ -22,7 +23,6 @@ import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;
 import org.simantics.browsing.ui.NodeContext.QueryKey;
 import org.simantics.browsing.ui.content.Labeler;
 import org.simantics.browsing.ui.content.Labeler.Modifier;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.threads.IThreadWorkQueue;
 
 /**
@@ -205,7 +205,7 @@ public interface GraphExplorer extends IAdaptable {
      */
     void setSelectionFilter(SelectionFilter f);
 
-    void setSelectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> f);
+    void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> f);
 
     //ISelectionProvider getSelectionProvider();
 
index 3972fd95c9317f58730eac5a193037a6ed840775..71d20dcce2760e2fc7d29f3fd05a5d3034cc53d2 100644 (file)
@@ -45,11 +45,11 @@ importJava "org.simantics.charts.ui.SCLChart" where
 Browses the given Model for its Charts and then returns them in a list.
 """
 chartsOf :: Model -> <ReadGraph> [Chart]
-chartsOf model = recurse (toResource model)
+chartsOf model = recurse model
   where
     recurse r = do
-        cs = resourceChildrenOf r 
-        charts = map fromResource $ filter isChart cs
+        cs = children r 
+        charts = filter isChart cs
         chartGrp = filter isChartGroup cs
         charts + concatMap recurse chartGrp
     isChart r = isInstanceOf r CHART.TimeSeriesChart
index 1358c402333b40a42d425e66acaef6faf339af42..5e4ef406db3b9185f22e553b43e88c90b1383656 100644 (file)
@@ -48,9 +48,9 @@ public final class Charts {
     public static HistorySamplerItem createHistorySamplerItem(ReadGraph graph, Resource subscriptionItem, ChartData data) throws DatabaseException {
 
         try {
-            Resource model = graph.syncRequest(new PossibleIndexRoot(subscriptionItem));
-            if (model == null) {
-                throw new DatabaseException("There is no model for " + subscriptionItem);
+            Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(subscriptionItem));
+            if (indexRoot == null) {
+                throw new DatabaseException("There is no index root for " + subscriptionItem);
             }
 
             ItemManager im = new ItemManager(data.history.getItems());
index a396d10dacef442fbe089af59e6cdb85b975f369..aeae9f5d3595f05bae50abc8cc168b892947c976 100644 (file)
@@ -41,7 +41,7 @@ import org.simantics.utils.FileUtils;
  * 
  * @author Tuukka Lehtonen
  */
-public class TrendSupport {
+public class TrendSupport implements ITrendSupport {
 
     // Input
     private IDynamicExperiment experiment;
@@ -170,4 +170,13 @@ public class TrendSupport {
         return finalPath.toFile();
     }
 
+    @Override
+    public void setChartData(ReadGraph graph) throws DatabaseException {
+    }
+
+    @Override
+    public ChartData getChartData() {
+       return chartData;
+    }
+    
 }
index 561843e20dc76e83c95f8ae16dfa5072c35c6f6b..4b8c3cbad87dd015fe7f358eac8bdc088480d85a 100644 (file)
@@ -6,7 +6,8 @@ Bundle-Version: 1.1.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Require-Bundle: org.simantics.db.common;bundle-version="0.8.0",
  org.eclipse.core.runtime;bundle-version="3.6.0",
- gnu.trove3;bundle-version="3.0.0"
+ gnu.trove3;bundle-version="3.0.0",
+ org.slf4j.api
 Export-Package: org.simantics.db.impl,
  org.simantics.db.impl.exception,
  org.simantics.db.impl.graph,
index 31b585aaeeccd43cb2089ebe254d680c314a709b..5776857d330ad98374d9b8c07d575ddb0118f7b2 100644 (file)
@@ -14,14 +14,17 @@ package org.simantics.db.impl.query;
 import java.util.ArrayList;
 import java.util.Iterator;
 
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.DebugPolicy;
 import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.procedure.InternalProcedure;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 abstract public class CacheEntryBase extends CacheEntry {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(CacheEntryBase.class);
+    
        // Default level is something that is not quite a prospect but still allows for ordering within CacheCollectionResult 
        public static final short UNDEFINED_LEVEL = 5;
        
@@ -108,7 +111,7 @@ abstract public class CacheEntryBase extends CacheEntry {
                statusOrException = EXCEPTED;
                result = t;
        } else {
-               Logger.defaultLogError("Cache entry got excepted status after being discarded: " + getClass().getSimpleName(), t);
+               LOGGER.warn("Cache entry got excepted status after being discarded: " + getClass().getSimpleName(), t);
                result = t;
        }
     }
@@ -139,7 +142,7 @@ abstract public class CacheEntryBase extends CacheEntry {
     final public boolean assertPending() {
        boolean result = isPending();
        if(!result) {
-               System.err.println("Assertion failed, expected pending, got " + statusOrException);
+               LOGGER.warn("Assertion failed, expected pending, got " + statusOrException);
        }
        return result;
     }
index e5a14f77cd480102dad8cda01f65b41166c1f109..c466cb261cca975d10c16a70461eab15bb3f77b2 100644 (file)
@@ -141,8 +141,9 @@ public class URIToResource extends StringQuery<InternalProcedure<Integer>> {
                     }
                 }
                 
-                if(entry != null) entry.addOrSet(graph, graph.processor, new Integer(0));
-                procedure.execute(graph, new Integer(0));
+                Integer zero = 0;
+                if(entry != null) entry.addOrSet(graph, graph.processor, zero);
+                procedure.execute(graph, zero);
 
             }
 
index c8efdc2509edd9e5fedd59f32f9e5b8ad68bfdc6..abd6e1ba54ef1203f7508ee285b8e26a4ed442fd 100644 (file)
@@ -14,6 +14,7 @@ package org.simantics.db.indexing;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
+import java.util.ArrayList;
 
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
@@ -22,6 +23,7 @@ import org.simantics.db.common.request.IndexRoot;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.indexing.internal.IndexChangedWriter;
 import org.simantics.db.layer0.adapter.GenericRelationIndex;
 import org.simantics.db.layer0.genericrelation.IndexedRelations;
 import org.simantics.db.layer0.internal.SimanticsInternal;
@@ -75,7 +77,10 @@ public final class DatabaseIndexing {
             return;
         if (DEBUG)
             System.out.println("Marking all indexes dirty");
-        getAllDirtyFile().createNewFile();
+        File allDirtyFile = getAllDirtyFile();
+        if (allDirtyFile.createNewFile()) {
+            FileUtils.syncFile(allDirtyFile);
+        }
     }
 
     public static void clearAllDirty() throws IOException {
@@ -85,39 +90,61 @@ public final class DatabaseIndexing {
         File indexBase = getIndexBaseLocation();
         if (!indexBase.exists() || !indexBase.isDirectory())
             return;
-        delete(getAllDirtyFile());
 
         forEachIndexPath(new Procedure<File, IOException>() {
             @Override
             public void execute(File indexPath) throws IOException {
-                delete(getChangedFile(indexPath));
+                getChangedFile(indexPath).delete();
             }
         });
-    }
 
+        getAllDirtyFile().delete();
+    }
+    
     /**
      * Internal to indexing, invoked by {@link IndexedRelationsImpl} which
      * doesn't want to throw these exceptions forward. Just log it.
      * 
      * @param indexPath
      */
-    static void markIndexChanged(File indexPath) {
-        if (!indexPath.exists())
-            throw new IllegalArgumentException("index path " + indexPath + " does not exist");
-        if (!indexPath.isDirectory())
-            throw new IllegalArgumentException("index path " + indexPath + " is not a directory");
+    static void markIndexChanged(Session session, File indexPath) {
+        if (DEBUG)
+            System.out.println("Marking index dirty: " + indexPath);
         try {
-            if (DEBUG)
-                System.out.println("Marking index dirty: " + indexPath);
-            getChangedFile(indexPath).createNewFile();
+            File changedFile = getChangedFile(indexPath);
+            // Mark change only once per DB session.
+            if (getIndexChangedWriter(session).markDirty(changedFile)) {
+                if (indexPath.mkdirs()) {
+                    if (changedFile.createNewFile()) {
+                        FileUtils.syncFile(changedFile);
+                    }
+                }
+            }
         } catch (IOException e) {
             Logger.defaultLogError(e);
         }
     }
 
+    private static IndexChangedWriter getIndexChangedWriter(Session session) {
+        IndexChangedWriter writer = session.peekService(IndexChangedWriter.class);
+        if (writer == null) {
+            synchronized (IndexChangedWriter.class) {
+                if (writer == null)
+                    session.registerService(IndexChangedWriter.class, writer = new IndexChangedWriter());
+            }
+        }
+        return writer;
+    }
+
     public static void deleteAllIndexes() throws IOException {
         File indexBase = DatabaseIndexing.getIndexBaseLocation();
-        delete(indexBase);
+
+        ArrayList<String> filter = new ArrayList<>(2);
+        filter.add(getAllDirtyFile().getAbsolutePath());
+        filter.add(indexBase.getAbsolutePath());
+
+        FileUtils.deleteAllWithFilter(indexBase, filter);
+        FileUtils.deleteAll(indexBase);
     }
 
     public static void deleteIndex(final Resource relation, final Resource modelPart) throws DatabaseException {
@@ -148,7 +175,13 @@ public final class DatabaseIndexing {
     public static void deleteIndex(File indexPath) throws IOException {
         if (DEBUG)
             System.out.println("Deleting index " + indexPath);
-        delete(indexPath);
+
+        ArrayList<String> filter = new ArrayList<>(2);
+        filter.add(getChangedFile(indexPath).getAbsolutePath());
+        filter.add(indexPath.getAbsolutePath());
+
+        FileUtils.deleteAllWithFilter(indexPath, filter);
+        FileUtils.deleteAll(indexPath);
     }
 
     public static void validateIndexes() throws IOException {
@@ -161,7 +194,7 @@ public final class DatabaseIndexing {
             // Make sure that index-base is a valid directory
             if (DEBUG)
                 System.out.println(indexBase + " is not a directory! Removing it.");
-            delete(indexBase);
+            FileUtils.deleteAll(indexBase);
             indexBase.mkdirs();
             return;
         }
@@ -169,7 +202,6 @@ public final class DatabaseIndexing {
         if (allDirtyFile.isFile()) {
             if (DEBUG)
                 System.out.println("All indexes marked dirty, removing them.");
-            delete(allDirtyFile);
             deleteAllIndexes();
         } else {
             forEachIndexPath(new Procedure<File, IOException>() {
@@ -186,12 +218,6 @@ public final class DatabaseIndexing {
         }
     }
 
-
-    private static void delete(File fileOrDir) throws IOException {
-        if (fileOrDir.exists())
-            FileUtils.deleteAll(fileOrDir);
-    }
-
     interface Procedure<T, E extends Throwable> {
         void execute(T t) throws E;
     }
index aaadc4704d487ddbdce71af7e59a78522648657b..1b4d62a1d6c6cf9c6d199b7454e713232c763526 100644 (file)
@@ -392,13 +392,13 @@ public class IndexedRelationsImpl implements IndexedRelations {
         
         try {
                
+               DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
                if(!searcher.startAccess(null, processor.getSession(), true)) {
                 // Could not write index for some reason. Ignore and let the next index query reinitialize the index.
                        return;
                }
                
             searcher.insertIndex(progress.newChild(40), relation, 1, documents);
-            DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
             
         } catch (InvalidResourceReferenceException e) {
             throw new IndexException(e);
@@ -429,13 +429,13 @@ public class IndexedRelationsImpl implements IndexedRelations {
         LockHandle handle = lock(processor, Pair.make(relationResource, input), true);
         try {
                
+            DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
                if(!searcher.startAccess(null, processor.getSession(), true)) {
                 // Could not write index for some reason. Ignore and let the next index query reinitialize the index.
                        return;
                }
                
             searcher.removeIndex(progress.newChild(40), relation, processor, key, keyValues);
-            DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
             
         } catch (DatabaseException e) {
             throw new IndexException(e);
@@ -492,13 +492,12 @@ public class IndexedRelationsImpl implements IndexedRelations {
 
         try {
                
+               DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
                if(!searcher.startAccess(null, processor.getSession(), true)) {
                 // Could not write index for some reason. Ignore and let the next index query reinitialize the index.
                        return true;
                }
-            didChange = searcher.replaceIndex(progress.newChild(40), key, keyValues, relation, 1, documents);
-            if(didChange)
-               DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
+            searcher.replaceIndex(progress.newChild(40), key, keyValues, relation, 1, documents);
             
         } catch (InvalidResourceReferenceException e) {
             throw new IndexException(e);
diff --git a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/internal/IndexChangedWriter.java b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/internal/IndexChangedWriter.java
new file mode 100644 (file)
index 0000000..c0e97a2
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.indexing.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An internal in-memory container for telling whether a certain index has been
+ * changed since the platform was last started up. 
+ * 
+ * @author Jussi Koskela
+ * @since 1.28.0
+ */
+public class IndexChangedWriter {
+       private Set<String> dirtyFiles = new HashSet<>();
+
+       public synchronized boolean markDirty(File dirtyFile) throws IOException {
+               return dirtyFiles.add(dirtyFile.getAbsolutePath());
+       }
+}
index e16d07cf0469ace76097b80204a264476a5755aa..2a575a578769db92b912ca66e1c02ed427aab314 100644 (file)
@@ -33,6 +33,7 @@ import org.simantics.graph.db.MissingDependencyException;
 import org.simantics.graph.db.TransferableGraphImporter;
 import org.simantics.graph.representation.Root;
 import org.simantics.layer0.Layer0;
+import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.Triple;
 
 public class SharedOntologyImportAdvisor extends AbstractImportAdvisor2 {
@@ -87,7 +88,15 @@ public class SharedOntologyImportAdvisor extends AbstractImportAdvisor2 {
                }
                
                Resource existing = graph.getPossibleResource(uri);
-               if(existing != null) throw new DatabaseException("Shared library " + uri + " exists already.");
+               if(existing != null) {
+                       if(graph.isInstanceOf(existing, L0.ExternalEntity)) {
+                               created.put(r, existing);
+                   addRootInfo(r, r.name, existing);
+                               return null;
+                       } else {
+                               throw new DatabaseException("Shared library " + uri + " exists already.");
+                       }
+               }
                
                Resource type = graph.getPossibleResource(r.type);
                if(type == null) { 
@@ -124,43 +133,62 @@ public class SharedOntologyImportAdvisor extends AbstractImportAdvisor2 {
     public void beforeWrite(WriteOnlyGraph graph, TransferableGraphImporter process)
             throws DatabaseException {
        
-        graph.markUndoPoint();
-        if(published) {
-               XSupport xs = graph.getService(XSupport.class);
-               xs.setServiceMode(false, true);
-        }
-        
-        graph.setClusterSet4NewResource(graph.getRootLibrary());
-        graph.flushCluster();
-
-        for(Map.Entry<Root, Triple<Resource, Resource, List<String>>> entry : toCreate.entrySet()) {
-               
-            Triple<Resource, Resource, List<String>> recipe = entry.getValue();
-
-            Resource base = recipe.first;
-            for(int i=0;i<recipe.third.size()-1;i++) {
-                Resource lib = graph.newResource();
-                graph.claim(lib, L0.InstanceOf, null, L0.Library);
-                graph.addLiteral(lib, L0.HasName, L0.NameOf, URIStringUtils.unescape( recipe.third.get(i) ), Bindings.STRING);
-                graph.claim(base, L0.ConsistsOf, L0.PartOf, lib);
-                base = lib;
-            }
+       XSupport xs = graph.getService(XSupport.class);
 
-            Resource lib = graph.newResource();
-            graph.newClusterSet(lib);
-            graph.setClusterSet4NewResource(lib);
-            graph.claim(lib, L0.InstanceOf, null, recipe.second);
-            String name = URIStringUtils.unescape( recipe.third.get(recipe.third.size()-1) );
-            graph.addLiteral(lib, L0.HasName, L0.NameOf, name, Bindings.STRING);
-            graph.claim(base, L0.ConsistsOf, L0.PartOf, lib);
+       Pair<Boolean,Boolean> mode = xs.getServiceMode();
+       
+       try {
+
+               graph.markUndoPoint();
+               
+               if(published) {
+                       xs.setServiceMode(true, true);
+               } else {
+                       xs.setServiceMode(true, mode.second);
+               }
+               
+               graph.setClusterSet4NewResource(graph.getRootLibrary());
+               graph.flushCluster();
+               
+               for(RootInfo info : getRootInfo()) {
+                       // At this stage these are existing L0.ExternalEntity instances that are now being imported.
+                       graph.deny(info.resource, L0.InstanceOf, null, L0.ExternalEntity, null);
+               }
+               
+               for(Map.Entry<Root, Triple<Resource, Resource, List<String>>> entry : toCreate.entrySet()) {
+                       
+                   Triple<Resource, Resource, List<String>> recipe = entry.getValue();
+       
+                   Resource base = recipe.first;
+                   for(int i=0;i<recipe.third.size()-1;i++) {
+                       Resource lib = graph.newResource();
+                       graph.claim(lib, L0.InstanceOf, null, L0.Library);
+                       graph.addLiteral(lib, L0.HasName, L0.NameOf, URIStringUtils.unescape( recipe.third.get(i) ), Bindings.STRING);
+                       graph.claim(base, L0.ConsistsOf, L0.PartOf, lib);
+                       base = lib;
+                   }
+       
+                   Resource lib = graph.newResource();
+                   graph.newClusterSet(lib);
+                   graph.setClusterSet4NewResource(lib);
+                   graph.claim(lib, L0.InstanceOf, null, recipe.second);
+                   String name = URIStringUtils.unescape( recipe.third.get(recipe.third.size()-1) );
+                   graph.addLiteral(lib, L0.HasName, L0.NameOf, name, Bindings.STRING);
+                   graph.claim(base, L0.ConsistsOf, L0.PartOf, lib);
+       
+                   addRootInfo(entry.getKey(), name, lib);
+                   
+                   created.put(entry.getKey(), lib);
+                   
+               }
+       
+               graph.flushCluster();
+               
+       } finally {
 
-            addRootInfo(entry.getKey(), name, lib);
-            
-            created.put(entry.getKey(), lib);
-            
-        }
-        
-        graph.flushCluster();
+               xs.setServiceMode(mode.first, mode.second);
+               
+       }
         
     }
 
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigratedImportResult.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigratedImportResult.java
new file mode 100644 (file)
index 0000000..1981ae4
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.layer0.migration;
+
+import java.util.Collection;
+
+import org.simantics.db.Resource;
+import org.simantics.db.exception.AssumptionException;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.graph.db.ImportResult;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class MigratedImportResult {
+
+       /**
+        * The root resources created by the import process.
+        */
+       public final Collection<Resource> roots;
+
+       public final ImportResult tgResult;
+
+       public MigratedImportResult(Collection<Resource> roots, ImportResult tgResult) {
+               this.roots = roots;
+               this.tgResult = tgResult;
+       }
+
+       public Resource singleRoot() throws DatabaseException {
+               int s = roots.size();
+               if (s != 1)
+                       throw new AssumptionException("No single imported root found, roots are: " + roots);
+               return roots.iterator().next();
+       }
+
+       public boolean hasMissingExternals() {
+               return tgResult != null ? tgResult.hasMissingExternals() : false;
+       }
+
+}
index bf860e44dafe32c400737d9804c95e458a7a61c8..2b19da58607dd66fa9368296ccf99a11100f30c2 100644 (file)
@@ -37,12 +37,14 @@ import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor;
 import org.simantics.db.layer0.internal.SimanticsInternal;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;
+import org.simantics.db.layer0.util.TGTransferableGraphSource;
 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
 import org.simantics.db.request.Read;
 import org.simantics.db.service.ManagementSupport;
 import org.simantics.db.service.SerialisationSupport;
 import org.simantics.graph.db.IImportAdvisor;
 import org.simantics.graph.db.IImportAdvisor2;
+import org.simantics.graph.db.ImportResult;
 import org.simantics.graph.db.StreamingTransferableGraphFileReader;
 import org.simantics.graph.db.TGStatusMonitor;
 import org.simantics.graph.db.TransferableGraphImporter;
@@ -201,8 +203,8 @@ public class MigrationStateImpl implements MigrationState {
                                };
                                // Make sure that the supplied advisor is redirected to temp
                                advisor.redirect(indexRoot);
-                
-                TransferableGraphs.importGraph1WithMonitor(session, tg, advisor, new TGStatusMonitor() {
+
+                ImportResult ir = TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg), advisor, new TGStatusMonitor() {
                     @Override
                     public void status(int percentage) {
                         monitor.subTask("Importing model from file (" + percentage + "%)");
@@ -212,7 +214,8 @@ public class MigrationStateImpl implements MigrationState {
                         return monitor.isCanceled();
                     }
                 });
-                
+
+                setProperty(MigrationStateKeys.IMPORT_RESULT, ir);
                 setProperty(MigrationStateKeys.CURRENT_RESOURCE, indexRoot);
                 setProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES, new ArrayList<>(advisor.getRoots()));
                 setProperty(MigrationStateKeys.DATABASE_REVISION_AFTER_TG_IMPORT, session.getService(ManagementSupport.class).getHeadRevisionId());
@@ -258,7 +261,7 @@ public class MigrationStateImpl implements MigrationState {
                                // Make sure that the supplied advisor is redirected to temp
                                advisor.redirect(indexRoot);
                                
-                TransferableGraphs.importGraph1(session, tgs, advisor, new TGStatusMonitor() {
+                ImportResult ir = TransferableGraphs.importGraph1(session, tgs, advisor, new TGStatusMonitor() {
                     @Override
                     public void status(int percentage) {
                         monitor.subTask("Importing model from file (" + percentage + "%)");
@@ -269,6 +272,7 @@ public class MigrationStateImpl implements MigrationState {
                     }
                 });
 
+                setProperty(MigrationStateKeys.IMPORT_RESULT, ir);
                 setProperty(MigrationStateKeys.CURRENT_RESOURCE, indexRoot);
                 setProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES, new ArrayList<>(advisor.getRoots()));
                 setProperty(MigrationStateKeys.DATABASE_REVISION_AFTER_TG_IMPORT, session.getService(ManagementSupport.class).getHeadRevisionId());
index a1a7a82ae04605444d241e19c3c4f95739772ec4..9a5ac6fdae23196e666ef9534cd95b7df0732754 100644 (file)
@@ -15,6 +15,7 @@ import java.io.PrintWriter;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.simantics.db.Session;
+import org.simantics.graph.db.ImportResult;
 
 public interface MigrationStateKeys {
 
@@ -51,6 +52,12 @@ public interface MigrationStateKeys {
        public final static String TG_EXTENSIONS = "tgExtensions";
        public final static String CURRENT_RESOURCE = "currentResource";
        public final static String IMPORT_ADVISOR = "importAdvisor";
+
+    /**
+     * Used for storing the {@link ImportResult} resulting from the TG import.
+     */
+    public final static String IMPORT_RESULT = "importResult";
+
     /**
      * All root resources of the imported material as
      * Collection&lt;Resource&gt;.
index 052bc6e6fb393beb39f2f0e1e4b93ef7852f9eb8..5f20036a54e1ea75638fba8699a1f7044e8cb26c 100644 (file)
  *******************************************************************************/
 package org.simantics.db.layer0.migration;
 
+import java.io.DataInputStream;
 import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.simantics.databoard.Bindings;
+import org.simantics.databoard.adapter.AdaptException;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.container.DataContainer;
+import org.simantics.databoard.container.DataContainers;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.WriteOnlyGraph;
 import org.simantics.db.common.CommentMetadata;
+import org.simantics.db.common.primitiverequest.PossibleResource;
 import org.simantics.db.common.request.BinaryRead;
 import org.simantics.db.common.request.FreshEscapedName;
 import org.simantics.db.common.request.UnaryRead;
@@ -42,10 +50,12 @@ import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;
 import org.simantics.db.layer0.adapter.impl.SharedOntologyImportAdvisor;
 import org.simantics.db.layer0.adapter.impl.TrashBinRemover;
 import org.simantics.db.layer0.internal.SimanticsInternal;
+import org.simantics.db.layer0.util.ExternalDownloadBean;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.util.TGTransferableGraphSource;
 import org.simantics.db.service.XSupport;
 import org.simantics.graph.db.IImportAdvisor;
+import org.simantics.graph.db.ImportResult;
 import org.simantics.graph.db.MissingDependencyException;
 import org.simantics.graph.db.TransferableGraphException;
 import org.simantics.graph.representation.Identity;
@@ -155,7 +165,6 @@ public class MigrationUtils {
     }
     
     
-    @SuppressWarnings("deprecation")
        public static Collection<MigrationStep> getMigrationSteps(DataContainer header) throws DatabaseException {
        
        return SimanticsInternal.sync(new BinaryRead<String,Integer,Collection<MigrationStep>>(header.format, header.version) {
@@ -299,48 +308,57 @@ public class MigrationUtils {
         return t != null ? t : defaultValue;
     }
 
-    public static Resource importSharedOntology(Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
+    public static MigratedImportResult importSharedOntology(Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
        return importSharedOntology(null, session, tg, published);
     }
 
-    public static Resource importSharedOntology(IProgressMonitor monitor, Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
+    public static MigratedImportResult importSharedOntology(IProgressMonitor monitor, Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
        
        if(monitor == null) monitor = new NullProgressMonitor();
        
+       Variant edbVariant = tg.extensions.get(ExternalDownloadBean.EXTENSION_KEY);
+       if(edbVariant != null) {
+               try {
+                               ExternalDownloadBean edb = (ExternalDownloadBean)edbVariant.getValue(ExternalDownloadBean.BINDING);
+                               for(Map.Entry<String, String> entry : edb.downloads.entrySet()) {
+                                       String uri = entry.getKey();
+                                       Resource existing = session.syncRequest(new PossibleResource(uri));
+                                       if(existing == null) {
+                                               String download = entry.getValue();
+                                                URL url = new URL(download);
+                                                DataContainer container = DataContainers.readFile(new DataInputStream(url.openStream()));
+                                                TransferableGraph1 dependencyTg = (TransferableGraph1) container.content.getValue(TransferableGraph1.BINDING);
+                                                importSharedOntology(monitor, session, dependencyTg, true);
+                                       }
+                               }
+                       } catch (AdaptException e) {
+                               throw new DatabaseException(e);
+                       } catch (MalformedURLException e) {
+                               throw new DatabaseException(e);
+                       } catch (IOException e) {
+                               throw new DatabaseException(e);
+                       }
+               
+       }
+       
         Collection<Identity> roots = TransferableGraphUtils.getRoots(tg);
         if(roots.size() == 1) {
-//             Identity id = roots.iterator().next();
-//             final Root root = (Root)id.definition;
-//             Resource rootResource = session.syncRequest(new WriteResultRequest<Resource>() {
-//                             @Override
-//                             public Resource perform(WriteGraph graph) throws DatabaseException {
-//                                     Resource type = graph.getResource(root.type);
-//                                     Resource existing = graph.getPossibleResource(root.name);
-//                                     if(existing != null) throw new DatabaseException("Shared library " + root.name + " exists already.");
-//                                     return Layer0Utils.applySCL("Simantics/SharedOntologies", "createSharedOntology", graph, root.name, type);
-//                             }
-//             });
             try {
-               
                 TGTransferableGraphSource tgSource = new TGTransferableGraphSource(tg);
                 SharedOntologyImportAdvisor advisor = new SharedOntologyImportAdvisor(published);
-//                TransferableGraphs.importGraph1(session, tgSource, advisor);
-                
-//                if (advisor.getRoots().size() == 1) {
-//                     return advisor.getRoots().iterator().next();
-//                }
-                               //TransferableGraphs.importGraph1(session, tg, new SharedOntologyImportAdvisor(), null);
 
                 MigrationState state = newState();
-                //state.setProperty(MigrationStateKeys.BASE_URI, AprosBuiltins.URIs.Migration);
                 state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, false);
                 state.setProperty(MigrationStateKeys.CURRENT_TGS, tgSource);
                 state.setProperty(MigrationStateKeys.SESSION, session);
                 state.setProperty(MigrationStateKeys.PROGRESS_MONITOR, monitor);
                 state.setProperty(MigrationStateKeys.CURRENT_DATA_CONTAINER, new DataContainer("sharedLibrary", 1, new Variant(TransferableGraph1.BINDING, tg)));
 
-                return MigrationUtils.importMigrated(monitor, session, null, state, advisor, null);
-                
+                MigrationUtils.importMigrated(monitor, session, null, state, advisor, null);
+
+                Collection<Resource> resultRoots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);
+                ImportResult result = state.getProperty(MigrationStateKeys.IMPORT_RESULT);
+                return new MigratedImportResult(resultRoots, result);
                        } catch (TransferableGraphException e) {
                                throw new DatabaseException(e);
                        } catch (MissingDependencyException e) {
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/PossibleVariableRepresents.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/PossibleVariableRepresents.java
new file mode 100644 (file)
index 0000000..bb6a77d
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.layer0.request;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.Variable;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class PossibleVariableRepresents extends VariableRead<Resource> {
+
+    public PossibleVariableRepresents(Variable var) {
+        super(var);
+    }
+
+    @Override
+    public Resource perform(ReadGraph graph) throws DatabaseException {
+        return variable.getPossibleRepresents(graph);
+    }
+
+}
index 39c661e4be2d6649b8bb85074b59fcc8e04a9eb0..d910f13ff946a77e40d9b2dce830c2020c678f40 100644 (file)
 package org.simantics.db.layer0.util;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 import org.simantics.db.AsyncReadGraph;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
+import org.simantics.db.ResourceMap;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
 import org.simantics.db.procedure.AsyncContextMultiProcedure;
-import org.simantics.db.service.CollectionSupport;
+import org.simantics.db.procedure.Procedure;
 import org.simantics.db.service.DirectQuerySupport;
 import org.simantics.layer0.Layer0;
 
 class ConsistsOfProcess {
 
-       final Set<Resource> result;
-       final AsyncContextMultiProcedure<Resource, Resource> structure;
+       final List<InternalEntry> result;
+       final AsyncContextMultiProcedure<InternalEntry, Resource> structure;
+       final AsyncContextMultiProcedure<InternalEntry, Resource> names;
 
-    public static Set<Resource> walk(ReadGraph graph, Collection<Resource> resources, Set<Resource> exclusions, boolean ignoreVirtual) throws DatabaseException {
-       ConsistsOfProcess process = new ConsistsOfProcess(graph, resources, exclusions, ignoreVirtual);
+    public static List<InternalEntry> walk(ReadGraph graph, ResourceMap<ExtentStatus> status, Collection<Resource> resources, Set<Resource> exclusions, boolean ignoreVirtual) throws DatabaseException {
+       ConsistsOfProcess process = new ConsistsOfProcess(graph, status, resources, exclusions, ignoreVirtual);
        return process.result;
     }
+    
+    static class InternalEntry {
+       public InternalEntry parent;
+       public Resource resource;
+       public String name;
+       InternalEntry(InternalEntry parent, Resource resource, String name) {
+               this.parent = parent;
+               this.resource = resource;
+               this.name = name;
+       }
+    }
        
-    private ConsistsOfProcess(ReadGraph graph, final Collection<Resource> resources, final Set<Resource> exclusions, final boolean ignoreVirtual) throws DatabaseException {
+    private ConsistsOfProcess(ReadGraph graph, ResourceMap<ExtentStatus> status, final Collection<Resource> resources, final Set<Resource> exclusions, final boolean ignoreVirtual) throws DatabaseException {
 
                final Layer0 L0 = Layer0.getInstance(graph);
                final DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
                
-               CollectionSupport cs = graph.getService(CollectionSupport.class);
-               result = cs.createSet();
+               result = new ArrayList<InternalEntry>();
+               
+               names = dqs.compileForEachObject(graph, L0.HasName, new AsyncContextMultiProcedure<InternalEntry, Resource>() {
+
+                       @Override
+                       public void execute(AsyncReadGraph graph, InternalEntry entry, Resource nameResource) {
+               
+                               if(status != null)
+                                       status.put(nameResource, ExtentStatus.EXCLUDED);
+                               
+                               graph.forPossibleValue(nameResource, new Procedure<String>() {
+
+                                       @Override
+                                       public void execute(String result) {
+                                               entry.name = result;
+                                       }
+
+                                       @Override
+                                       public void exception(Throwable t) {
+                                               Logger.defaultLogError(t);
+                                       }
+                                       
+                               });
+                       }
+
+                       @Override
+                       public void exception(AsyncReadGraph graph, Throwable throwable) {
+                               Logger.defaultLogError(throwable);
+                       }
+
+                       @Override
+                       public void finished(AsyncReadGraph graph) {
+                       }
+
+               });
                
-               structure = dqs.compileForEachObject(graph, L0.ConsistsOf, new AsyncContextMultiProcedure<Resource, Resource>() {
+               structure = dqs.compileForEachObject(graph, L0.ConsistsOf, new AsyncContextMultiProcedure<InternalEntry, Resource>() {
 
                        @Override
-                       public void execute(AsyncReadGraph graph, Resource parent, Resource child) {
+                       public void execute(AsyncReadGraph graph, InternalEntry parent, Resource child) {
                                
                                if(exclusions.contains(child)) return;
                                
-                               if(!ignoreVirtual || child.isPersistent())
-                                       if(result.add(child)) {
-                                               dqs.forEachObjectCompiled(graph, child, child, structure);
+                               if(!ignoreVirtual || child.isPersistent()) {
+                                       InternalEntry entry = new InternalEntry(parent, child, null);
+                                       if(result.add(entry)) {
+                                               dqs.forEachObjectCompiled(graph, child, entry, structure);
+                                               dqs.forEachObjectCompiled(graph, child, entry, names);
                                        }
+                               }
                                
                        }
 
@@ -61,8 +113,10 @@ class ConsistsOfProcess {
 
                        @Override
                        public void run(ReadGraph graph) throws DatabaseException {
-                               for(Resource r  : resources)
-                                       dqs.forEachObjectCompiled(graph, r, r, structure);
+                               for(Resource r  : resources) {
+                                       InternalEntry root = new InternalEntry(null, r, null);
+                                       dqs.forEachObjectCompiled(graph, r, root, structure);
+                               }
                        }
                        
                });
index b55f0a3d2d0b9c1ebc4e7b2627b8793f375fafd5..bd67680db6704f73bbe3a73d69aaa7774f8d3b5f 100644 (file)
@@ -5,6 +5,7 @@ import java.io.InputStream;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
@@ -25,6 +26,7 @@ import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.CancelTransactionException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
+import org.simantics.db.layer0.util.ConsistsOfProcess.InternalEntry;
 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest.Expansion3;
 import org.simantics.db.service.CollectionSupport;
 import org.simantics.db.service.SerialisationSupport;
@@ -502,7 +504,10 @@ public class DomainProcessor3 {
             this.datatypeBinding = Bindings.getBindingUnchecked(Datatype.class);
             this.datatypeSerializer = graph.getService(Databoard.class).getSerializerUnchecked(this.datatypeBinding);
 
-            for(Resource r : ConsistsOfProcess.walk(graph, fringe, exclusions, ignoreVirtual)) {
+            state.internalEntries = ConsistsOfProcess.walk(graph, status, fringe, exclusions, ignoreVirtual); 
+            
+            for(InternalEntry entry : state.internalEntries) {
+               Resource r = entry.resource;
                 if (status.put(r, ExtentStatus.INTERNAL) == null) {
                     if(ModelTransferableGraphSourceRequest.LOG) {
                         String URI = graph.getPossibleURI(r);
index f1dc02242eafdd984d582c701ba573c935c2f649..3f25410187768519082691dad43bd558f1c3d98b 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.db.layer0.util;
 
 import java.io.DataOutputStream;
+import java.util.List;
 import java.util.TreeMap;
 
 import org.eclipse.core.runtime.SubMonitor;
@@ -31,5 +32,6 @@ public class DomainProcessorState {
 
        public SubMonitor monitor;
        public TGValueModifier valueModifier;
+       public List<ConsistsOfProcess.InternalEntry> internalEntries;
 
 }
\ No newline at end of file
index 3ccdd691854cc3bd2b961a1b1009fb4180dfa631..d62cc1876d6be1b4d98ba1391e676333383234f6 100644 (file)
@@ -36,7 +36,7 @@ public class ExtendedUris {
                 String name = URIStringUtils.unescape(escapedName);
                 parent = graph.syncRequest(new UnescapedChildMapOfResource(parent)).get(name);
                 if(parent == null)
-                    throw new DatabaseException("Didn't find a child " + name);
+                    throw new DatabaseException("Didn't find a child " + name + " for " + uri.substring(0, beginPos));
             }
             else if(c == '#') {
                 String escapedName = uri.substring(beginPos+1, endPos);
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ExternalDownloadBean.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ExternalDownloadBean.java
new file mode 100644 (file)
index 0000000..6dd2b84
--- /dev/null
@@ -0,0 +1,20 @@
+package org.simantics.db.layer0.util;
+
+import java.util.TreeMap;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+
+public class ExternalDownloadBean {
+
+       public static final String EXTENSION_KEY = ExternalDownloadBean.class.getSimpleName();
+       
+       public static final Binding BINDING = Bindings.getBindingUnchecked(ExternalDownloadBean.class);
+       
+       public TreeMap<String,String> downloads = new TreeMap<>();
+       
+       public ExternalDownloadBean(TreeMap<String,String> downloads) {
+               this.downloads = downloads;
+       }
+
+}
index 888e5fe4e312af10d98af326966b6e2ad42e7894..adc51c16d88ef0f74f1f849f421e9156398c69f1 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.SubMonitor;
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.Datatypes;
@@ -1234,6 +1235,10 @@ public class Layer0Utils {
        return Layer0.getInstance(graph).String;
     }
 
+    public static void emptyTrashBin() throws ServiceException {
+        emptyTrashBin(new NullProgressMonitor());
+    }
+
     public static void emptyTrashBin(IProgressMonitor monitor) throws ServiceException {
         emptyTrashBin(monitor, SimanticsInternal.getSession(), SimanticsInternal.getProject());
     }
@@ -1281,15 +1286,31 @@ public class Layer0Utils {
                 return;
             mon.subTask("Purging Database");
             mon.newChild(1000);
-            XSupport xs = session.getService(XSupport.class);
-            xs.purge();
+            purgeDatabase(monitor, session);
         } catch (CancelTransactionException e) {
             // Ignore.
         } catch (DatabaseException e) {
             throw new ServiceException(e);
         }
     }
-    
+
+    public static void purgeDatabase() throws ServiceException {
+       purgeDatabase(new NullProgressMonitor());
+    }
+
+    public static void purgeDatabase(final IProgressMonitor monitor) throws ServiceException {
+       purgeDatabase(monitor, SimanticsInternal.getSession());
+    }
+
+    public static void purgeDatabase(final IProgressMonitor monitor, Session session) throws ServiceException {
+       try {
+               XSupport xs = session.getService(XSupport.class);
+               xs.purge();
+       } catch (DatabaseException e) {
+               throw new ServiceException(e);
+       }
+    }
+
     public static Resource getSingleDomainOf(ReadGraph graph, Resource type, Resource target) throws DatabaseException {
        Resource result = null;
        for(Resource candidate : getDomainOf(graph, type).values()) {
@@ -1328,6 +1349,18 @@ public class Layer0Utils {
        return null;
     }
     
+    public static Resource getPossiblePredicateByLabel(ReadGraph graph, Resource instance, String predicateName) throws DatabaseException {
+       Layer0 L0 = Layer0.getInstance(graph);
+       for(Resource type : graph.getPrincipalTypes(instance)) {
+               Map<String, Resource> domainOf = getDomainOf(graph, type);
+               for(Resource r : domainOf.values()) {
+                       String label = graph.getPossibleRelatedValue(r, L0.HasLabel, Bindings.STRING);
+                       if(predicateName.equals(label))
+                               return r;
+               }
+       }
+       return null;
+    }
     
     public static void claimLiteralDataboard(WriteGraph graph, Resource container, Resource property, String valueText) throws DatabaseException {
 
index 8602da82789d97de8830f1927dcd4b5d53c7295b..e7fa24124a2ca1a72fca4955d320e385b87368de 100644 (file)
@@ -27,16 +27,20 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.RuntimeDatabaseException;
 import org.simantics.db.exception.ValidationException;
 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
+import org.simantics.db.layer0.util.ConsistsOfProcess.InternalEntry;
 import org.simantics.db.layer0.util.TransferableGraphConfiguration2.RootSpec;
 import org.simantics.db.service.SerialisationSupport;
 import org.simantics.graph.db.TransferableGraphSource;
 import org.simantics.graph.representation.External;
 import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.Internal;
 import org.simantics.graph.representation.Root;
 import org.simantics.graph.representation.Value;
 import org.simantics.layer0.Layer0;
 
 import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
 import gnu.trove.procedure.TIntIntProcedure;
 
 public class ModelTransferableGraphSource implements TransferableGraphSource {
@@ -51,7 +55,8 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
        private volatile boolean closed = false;
 
        TIntArrayList externalParents = new TIntArrayList();
-       ArrayList<String> externalNames = new ArrayList<String>();
+       ArrayList<String> externalNames = new ArrayList<>();
+       TreeMap<String,String> downloads = new TreeMap<String,String>();
 
        public ModelTransferableGraphSource(final ReadGraph graph, TransferableGraphConfiguration2 configuration, final DomainProcessorState state, File ... fs) throws DatabaseException {
 
@@ -79,7 +84,7 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                
                this.externalBase = state.id;
 
-               final Collection<String> errors = new HashSet<String>();
+               final Collection<String> errors = new HashSet<>();
 
                // All resource considered as not internal by domain processor. Can also contain roots.
                int[] externals = state.externals.toArray();
@@ -105,7 +110,7 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                });
                
                if(!errors.isEmpty()) {
-                       ArrayList<String> sorted = new ArrayList<String>(errors);
+                       ArrayList<String> sorted = new ArrayList<>(errors);
                        Collections.sort(sorted);
                        StringBuilder message = new StringBuilder();
                        message.append("Errors in exported model:\n");
@@ -118,6 +123,8 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                
                this.resourceCount = state.id;
                
+               state.extensions.put(ExternalDownloadBean.EXTENSION_KEY, new Variant(ExternalDownloadBean.BINDING, new ExternalDownloadBean(downloads)));
+               
        }
 
        int indent = 0;
@@ -200,6 +207,11 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                        state.ids.put(r, state.id);
                        // Ensure that this resource is included into the set of externals to maintain the total number of externals 
                        state.externals.add(r);
+                       String download = graph.getPossibleRelatedValue(res, L0.Ontology_download, Bindings.STRING);
+                       if(download != null) {
+                               String uri = graph.getURI(res);
+                               downloads.put(uri, download);
+                       }
                        return state.id++;
                }
        }
@@ -380,13 +392,17 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                // TODO: this should be Root with name ""
                procedure.execute(getRootIdentity(state, support, graph.getRootLibrary()));
 
+               TIntObjectMap<Identity> internalMap = new TIntObjectHashMap<>(100, 0.5f, Integer.MIN_VALUE);
+
                // Declare internal and external roots
                for(RootSpec r : configuration.roots) {
                        Resource type = graph.getPossibleType(r.resource, L0.Entity);
                        if(type == null) type = L0.Entity;
-                       procedure.execute(new Identity(
-                                       state.ids.get(support.getTransientId(r.resource)),
-                                       new Root(r.name, graph.getURI(type))));
+                       int id = state.ids.get(support.getTransientId(r.resource));
+                       Root root = new Root(r.name, graph.getURI(type));
+                       Identity rootId = new Identity(id,root);
+                       internalMap.put(id, rootId);
+                       procedure.execute(rootId);
                }
 
                for(int i = 0; i < state.externals.size() ; i++) {
@@ -394,8 +410,27 @@ public class ModelTransferableGraphSource implements TransferableGraphSource {
                        String name = externalNames.get(i);
                        procedure.execute(new Identity(externalBase + i, new External(parent,name)));
        }
+               
+               if(state.internalEntries != null) {
+                       for(InternalEntry ie : state.internalEntries) {
+                               if(ie.parent != null && ie.name != null) {
+                                       procedure.execute(resolveInternal(graph, support, ie, internalMap));
+                               }
+                       }
+               }
        
        }
+       
+       private Identity resolveInternal(ReadGraph graph, SerialisationSupport ss, InternalEntry entry, TIntObjectMap<Identity> internalMap) throws DatabaseException {
+               int id = state.ids.get(ss.getTransientId(entry.resource));
+               Identity existing = internalMap.get(id);
+               if(existing != null) return existing;
+               Identity parent = resolveInternal(graph, ss, entry.parent, internalMap);
+               Identity result = new Identity(id,
+                               new Internal(parent.resource, entry.name));
+               internalMap.put(id, result);
+               return result;
+       }
 
        @Override
        public TreeMap<String, Variant> getExtensions() {
index 9b85adf8faadc90cac8a09345f02ce36de40ba69..c7e697e6291773b58e44d8bd3a8c2afbf0952442 100644 (file)
  *******************************************************************************/
 package org.simantics.db.layer0.util;
 
-import gnu.trove.list.array.TIntArrayList;
-import gnu.trove.map.hash.TIntIntHashMap;
-import gnu.trove.map.hash.TLongObjectHashMap;
-import gnu.trove.procedure.TIntProcedure;
-import gnu.trove.procedure.TLongObjectProcedure;
-import gnu.trove.set.TIntSet;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
 import java.io.DataOutput;
 import java.io.DataOutputStream;
 import java.io.FileNotFoundException;
@@ -30,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -54,6 +46,7 @@ import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.SubgraphAdvisor;
 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
+import org.simantics.db.layer0.util.ConsistsOfProcess.InternalEntry;
 import org.simantics.db.procedure.AsyncProcedure;
 import org.simantics.db.request.AsyncRead;
 import org.simantics.db.service.ClusteringSupport;
@@ -70,6 +63,15 @@ import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.threads.logger.ITask;
 import org.simantics.utils.threads.logger.ThreadLogger;
 
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.procedure.TLongObjectProcedure;
+import gnu.trove.set.TIntSet;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
 public class Subgraphs {
 
        public static String LOG_FILE = "export.log";
@@ -989,7 +991,9 @@ public class Subgraphs {
              * ï¿½ All o are internal
              * ï¿½ All stm are included
                         */
-                       for(Resource r : ConsistsOfProcess.walk(graph, fringe, exclusions, true)) {
+                       List<InternalEntry> entries = ConsistsOfProcess.walk(graph, null, fringe, exclusions, true); 
+                       for(InternalEntry entry : entries) {
+                               Resource r = entry.resource;
                                if (status.put(r, ExtentStatus.INTERNAL) == null) {
                                        String URI = graph.getPossibleURI(r);
                                        if(URI != null) log("URI INTERNAL " + URI);
index 82c20514c1aa858f625f89e7c0d028be3a9829cf..ffa39974315a1a06b50c57aada1816ae2677130e 100644 (file)
@@ -22,6 +22,7 @@ import org.simantics.db.Statement;
 import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.impl.EntityInstances.QueryIndex;
+import org.simantics.db.layer0.util.ConsistsOfProcess.InternalEntry;
 import org.simantics.db.layer0.util.DomainProcessor3.ExclusionDecision;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.runtime.function.Function1;
@@ -62,8 +63,9 @@ public class TGRepresentationUtils {
                         return new GUIDExclusionFunction(graph);
 
                     // The root is OK - check everything beneath
-                    for(Resource part : ConsistsOfProcess.walk(graph, Collections.singleton(r), Collections.emptySet(), true)) {
-                        if(findByIdentifier(graph, targetRoot, part))
+                    List<InternalEntry> entries = ConsistsOfProcess.walk(graph, null, Collections.singleton(r), Collections.emptySet(), true); 
+                    for(InternalEntry entry : entries) {
+                        if(findByIdentifier(graph, targetRoot, entry.resource))
                             return new GUIDExclusionFunction(graph);
                     }
                 }
index 1e8d2731ff4bb65bc47983d5f162412882e636c7..4ac08fc0b8a25ff02f1596f402e8c669d1634726 100644 (file)
@@ -16,6 +16,7 @@ import org.simantics.db.request.WriteTraits;
 import org.simantics.db.service.ClusterUID;
 import org.simantics.db.service.SerialisationSupport;
 import org.simantics.db.service.XSupport;
+import org.simantics.utils.datastructures.Pair;
 
 public class XSupportImpl implements XSupport {
     final private boolean DEBUG = false;
@@ -112,6 +113,12 @@ public class XSupportImpl implements XSupport {
                session.clusterSetsSupport.clear();
         }
     }
+    
+    @Override
+    public Pair<Boolean, Boolean> getServiceMode() {
+       return Pair.make((session.serviceMode & 1) == 1, (session.serviceMode & 2) == 2);
+    }
+    
     @Override
     public Resource convertDelayedResourceToResource(Resource resource) {
         return DelayedWriteGraph.convertDelayedResource(resource);
index 73594cddb4830fb2364ca83a94961847235fdf8d..8e08147c5b34a2c61af386c2154a0d5238f20707 100644 (file)
@@ -17,6 +17,7 @@ import org.simantics.db.WriteOnlyGraph;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ServiceException;
 import org.simantics.db.request.WriteTraits;
+import org.simantics.utils.datastructures.Pair;
 
 /**
  * @author TUOKSK
@@ -103,6 +104,7 @@ public interface XSupport {
      * @param createAsImmutable <code>true</code> to make all created clusters immutable
      */
     void setServiceMode(boolean allowImmutableWrites, boolean createAsImmutable);
+    Pair<Boolean,Boolean> getServiceMode();
 
     /**
      * If resource is acquired from DelayedWriteGraph during delayed write request then
index 33a3871fc992a5906d0066b237bca8b2a6dec512..c1c8ff68eac6ffba173e8f629300d798596d5f48 100644 (file)
Binary files a/bundles/org.simantics.desktop.ui.ontology/graph.tg and b/bundles/org.simantics.desktop.ui.ontology/graph.tg differ
index 72053ec5b6317e93ecee85e2c5d2afa528b8f79c..45f65af2648849bca8358e73bfd74d919dc95ece 100644 (file)
Binary files a/bundles/org.simantics.diagram.ontology/graph.tg and b/bundles/org.simantics.diagram.ontology/graph.tg differ
index 1ff8d39e0c760de9d7255648d7da777b20fda391..758aa4869a657e59abf396e14ca79840755f2a30 100644 (file)
@@ -13,7 +13,7 @@ Require-Bundle: org.simantics.utils.thread.swt,
  org.simantics.db.layer0;bundle-version="[1.0.0,2.0.0)",
  org.simantics.structural2;bundle-version="1.0.0",
  org.simantics.basicexpression;bundle-version="1.0.0",
javax.vecmath;bundle-version="1.0.0",
org.apache.commons.math3;bundle-version="3.6.1",
  org.simantics.layer0;bundle-version="1.0.0",
  org.simantics.diagram.ontology;bundle-version="1.0.0";visibility:=reexport,
  org.simantics.structural.ontology;bundle-version="1.0.0",
index 93957f0698fc0643691d0676039ce676e78f4b3c..98f229b91324b75a913be0df238676f52813cbec 100644 (file)
@@ -18,6 +18,7 @@ import java.util.EnumSet;
 import java.util.List;
 
 import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.ElementHints;
 import org.simantics.g2d.element.ElementUtils;
 import org.simantics.g2d.element.IElement;
 import org.simantics.g2d.element.SceneGraphNodeKey;
@@ -140,6 +141,7 @@ public class CompositeImage implements Image {
             SingleElementNode holder = node.getOrCreateNode(ElementUtils.generateNodeId(e), SingleElementNode.class);
             //SingleElementNode holder = parent.getOrCreateNode(ElementUtils.generateNodeId(e), SingleElementNode.class);
             holder.setZIndex(++zIndex);
+            holder.setKey(e.getHint(ElementHints.KEY_OBJECT));
 
             List<SceneGraph> nodeHandlers = ec.getItemsByClass(SceneGraph.class);
             for(SceneGraph n : nodeHandlers) {
index 03250d726c403ee9a864c3407584c7cb717e979b..e7bb472e4ed610450bdbb19a62df5be9f30d67de 100644 (file)
@@ -230,8 +230,8 @@ public class DefinedElementFactory extends ElementFactoryAdapter {
                                             DefaultTransform.INSTANCE,
                                             StaticSymbolImageInitializer.INSTANCE,
                                             new StaticSymbolImpl(img),
-                                            ImageClass.ImageElementHandler.INSTANCE,
-                                            new Terminals(terminals),
+                                            DefinedElementHandler.INSTANCE,
+                                            new DefinedElementTerminals(terminals),
                                             SimpleElementLayers.INSTANCE,
                                             PlainElementPropertySetter.INSTANCE
                                             ).setId(id));
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementHandler.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementHandler.java
new file mode 100644 (file)
index 0000000..b5cc293
--- /dev/null
@@ -0,0 +1,123 @@
+package org.simantics.diagram.adapter;
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.g2d.connection.handler.ConnectionHandler;
+import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.ElementHints;
+import org.simantics.g2d.element.ElementUtils;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.SceneGraphNodeKey;
+import org.simantics.g2d.element.handler.InternalSize;
+import org.simantics.g2d.element.handler.Outline;
+import org.simantics.g2d.element.handler.Resize;
+import org.simantics.g2d.element.handler.SceneGraph;
+import org.simantics.g2d.image.Image;
+import org.simantics.scenegraph.Node;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+
+public class DefinedElementHandler implements SceneGraph, InternalSize, Resize, Outline {
+
+       private static final long serialVersionUID = -2074850877791708846L;
+
+       public static final DefinedElementHandler INSTANCE = new DefinedElementHandler();
+
+    public static final Key  KEY_SG_NODE             = new SceneGraphNodeKey(Node.class, "IMAGE_SG_NODE");
+
+    protected Image getImage(IElement e) {
+        Image i = e.getHint(ElementHints.KEY_IMAGE);
+        if (i == null)
+            throw new IllegalStateException("element " + e + " has no ElementHints.KEY_IMAGE hint");
+        return i;
+    }
+
+    protected Key getNodeKey() {
+        return KEY_SG_NODE;
+    }
+
+    @Override
+    public void init(final IElement e, final G2DParentNode parent) {
+        Image i = getImage(e);
+        Node node = i.init(parent);
+        if (node != null)
+            e.setHint(getNodeKey(), node);
+        if(node instanceof IG2DNode) {
+               IG2DNode n = (IG2DNode)node;
+               AffineTransform at = ElementUtils.getTransform(e);
+               if(at != null) {
+                       n.setTransform(at); // FIXME: not tested..
+               }
+        }
+    }
+
+    public void cleanup(final IElement e) {
+        Node node = e.removeHint(getNodeKey());
+        if (node != null)
+            node.remove();
+    }
+    
+    public Rectangle2D imageBounds(IElement e) {
+       Image i = getImage(e);
+               return i.getBounds();
+    }
+
+    @Override
+    public Rectangle2D getBounds(IElement e, Rectangle2D size) {
+
+               if (size == null)
+                       size = new Rectangle2D.Double();
+
+       ElementClass ec = e.getElementClass();
+       if(ec.containsClass(ConnectionHandler.class)) {
+               size.setFrame(imageBounds(e));
+       } else {
+               IG2DNode node = e.getHint(getNodeKey());
+               if(node != null) {
+                       size.setFrame(node.getBoundsInLocal()); 
+               } else {
+                       size.setFrame(imageBounds(e));
+               }
+       }
+       
+               return size;
+               
+    }
+
+    @Override
+    public Double getFixedAspectRatio(IElement e) {
+        Image i = getImage(e);
+        Rectangle2D r = i.getBounds();
+        return r.getWidth() / r.getHeight();
+    }
+
+    @Override
+    public Rectangle2D getMaximumSize(IElement e) {
+        Image i = getImage(e);
+        return i.getBounds();
+    }
+
+    @Override
+    public Rectangle2D getMinimumSize(IElement e) {
+        Image i = getImage(e);
+        return i.getBounds();
+    }
+
+    @Override
+    public void resize(IElement e, Rectangle2D newSize) {
+    }
+
+    @Override
+    public Shape getElementShape(IElement e) {
+       
+        IG2DNode node = e.getHint(getNodeKey());
+        if (node == null)
+               throw new IllegalStateException();
+        return node.getBoundsInLocal();
+       
+    }
+       
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java
new file mode 100644 (file)
index 0000000..6f83954
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - #7119 initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.adapter;
+
+import java.awt.geom.AffineTransform;
+import java.util.Collection;
+
+import org.simantics.diagram.content.ResourceTerminal;
+import org.simantics.g2d.diagram.handler.Topology.Terminal;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.handler.TerminalLayout;
+import org.simantics.g2d.element.handler.TerminalTopology;
+import org.simantics.g2d.element.handler.impl.ObjectTerminal;
+import org.simantics.g2d.element.handler.impl.Terminals;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.utils.NodeUtil;
+
+/**
+ * A {@link TerminalTopology} and more specifically a {@link TerminalLayout}
+ * implementation that relies primarily on the scene graph and only secondarily
+ * on its internal datastructures to resolve terminal locations. This implementation
+ * is used to support dynamic terminals.
+ * 
+ * @author Antti Villberg
+ * @since 1.29.0
+ */
+public class DefinedElementTerminals extends Terminals {
+
+    private static final long serialVersionUID = -726490868093887444L;
+
+    public DefinedElementTerminals(Collection<ObjectTerminal> ts) {
+        super(ts);
+    }
+
+    private IG2DNode findResourceTerminalNode(IG2DNode node, ResourceTerminal rt) {
+        return (IG2DNode) NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
+            Object key = n.getKey();
+            if (rt.getResource().equals(key)) {
+                IG2DNode[] children = n.getSortedNodes();
+                if (children.length > 0)
+                    return children[0];
+                return n;
+            }
+            return null;
+        });
+    }
+
+    @Override
+    public AffineTransform getTerminalPosition(IElement e, Terminal t) {
+        if (t instanceof ResourceTerminal) {
+            ResourceTerminal rt = (ResourceTerminal) t;
+            IG2DNode node = e.getHint(DefinedElementHandler.KEY_SG_NODE);
+            if (node != null) {
+                IG2DNode n = findResourceTerminalNode(node, rt);
+                if (n != null) {
+                    return n.getTransform();
+                }
+            }
+        }
+
+        ObjectTerminal ti = terminalMap.get(t);
+        if (ti == null)
+            return null;
+        return new AffineTransform(ti.getTransform());
+    }
+
+}
\ No newline at end of file
index de99bd25fb8c626d7ca080161f77e0581681730b..99d9acb705388a6b85f242ec5485c08d1dcdc208 100644 (file)
@@ -69,12 +69,15 @@ import org.simantics.structural2.modelingRules.CPTerminal;
 import org.simantics.structural2.modelingRules.IAttachmentRelationMap;
 import org.simantics.structural2.modelingRules.IModelingRules;
 import org.simantics.utils.threads.CurrentThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.THashMap;
 import gnu.trove.set.hash.THashSet;
 
 public class RouteGraphUtils {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(RouteGraph.class);
     public static boolean DEBUG = false;
 
     public static final ILineEndStyle HEAD  = new ArrowLineEndStyle("fill 2 1 0");
@@ -341,7 +344,7 @@ public class RouteGraphUtils {
             RouteNode n1 = nodeByData.get(link.first());
             RouteNode n2 = nodeByData.get(link.second());
             if (n1 == null || n2 == null) {
-                System.err.println("Stray connection link found: " + link.toString(graph));
+                LOGGER.warn("Stray connection link found: " + link.toString(graph));
                 continue;
             }
             rg.link(n1, n2);
index 339f180e815525f2eeaf1fd49da350c3de9f6723..c62422d4a5fe0f52e875825b72ef2c663b96d76e 100644 (file)
@@ -25,8 +25,7 @@ import java.awt.geom.Rectangle2D;
 import java.util.EnumSet;
 import java.util.Map;
 
-import javax.vecmath.Vector2d;
-
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
 import org.simantics.db.layer0.variable.RVI;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.element.ElementClass;
@@ -680,11 +679,9 @@ public class MonitorClass {
             return Double.NaN;
         double angrad = Math.toRadians(angle);
 
-        Vector2d forcedAxis = new Vector2d(Math.cos(angrad), Math.sin(angrad));
-        Vector2d x = new Vector2d(tr.getScaleX(), tr.getShearX());
-        forcedAxis.normalize();
-        x.normalize();
-        double cosa = forcedAxis.dot(x);
+        Vector2D forcedAxis = new Vector2D(Math.cos(angrad), Math.sin(angrad));
+        Vector2D x = new Vector2D(tr.getScaleX(), tr.getShearX()).normalize();
+        double cosa = forcedAxis.dotProduct(x);
         double delta = Math.acos(cosa);
         return delta;
     }
index 85923bc35763923d5d2015178c867d73b84a98a7..4554decee2c01a41b032be9dab5c77ecec2af2f7 100644 (file)
@@ -34,7 +34,6 @@ import java.awt.font.TextLayout;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
-import java.io.IOException;
 import java.text.AttributedCharacterIterator;
 import java.text.AttributedString;
 import java.util.ArrayList;
@@ -75,13 +74,7 @@ import org.simantics.ui.dnd.PlaintextTransfer;
 import org.simantics.ui.fonts.Fonts;
 import org.simantics.utils.threads.AWTThread;
 
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Element;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.pdf.FontMapper;
-import com.lowagie.text.pdf.PdfFormField;
 import com.lowagie.text.pdf.PdfWriter;
-import com.lowagie.text.pdf.TextField;
 
 import gnu.trove.list.array.TIntArrayList;
 
@@ -99,7 +92,6 @@ import gnu.trove.list.array.TIntArrayList;
  * TODO:
  * o proper support for defining clipping bounds for the text (needed for page templates) (currently through fixedWidth)
  * o fix editing xOffset to work with fixed width and multi-line text
- * o 
  * 
  * @see Line
  * @see TextLayout
@@ -108,6 +100,12 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
 
     private static final long                serialVersionUID           = 654692698101485672L;
 
+    public static enum TextFlipping {
+        Disabled,
+        VerticalTextUpwards,
+        VerticalTextDownwards,
+    }
+
     /**
      * TODO: justify existence for this
      */
@@ -191,6 +189,8 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
     protected transient static final int STATE_X_OFFSET_IS_DIRTY = (1 << 7);
     protected static final int STATE_ALWAYS_ADD_LISTENERS = (1 << 8);
     protected static final int STATE_LISTENERS_ADDED = (1 << 9);
+    protected static final int STATE_AUTOMATIC_TEXT_FLIP_ENABLED = (1 << 10);
+    protected static final int STATE_AUTOMATIC_TEXT_FLIP_VERTICAL_DOWN = (1 << 11);
 
     /**
      * A combination of all the STATE_ constants defined in this class,
@@ -413,6 +413,21 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
         resetCaches();
     }
 
+    public void setAutomaticTextFlipping(TextFlipping type) {
+        switch (type) {
+        case Disabled:
+            clearState(STATE_AUTOMATIC_TEXT_FLIP_ENABLED | STATE_AUTOMATIC_TEXT_FLIP_VERTICAL_DOWN);
+            break;
+        case VerticalTextDownwards:
+            setState(STATE_AUTOMATIC_TEXT_FLIP_ENABLED | STATE_AUTOMATIC_TEXT_FLIP_VERTICAL_DOWN);
+            break;
+        case VerticalTextUpwards:
+            setState(STATE_AUTOMATIC_TEXT_FLIP_ENABLED);
+            clearState(STATE_AUTOMATIC_TEXT_FLIP_VERTICAL_DOWN);
+            break;
+        }
+    }
+
     @SyncField({"paddingX", "paddingY"})
     public void setPadding(double x, double y) {
         this.paddingX = x;
@@ -628,7 +643,8 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
         // Safety for not rendering when the scale of this text is too small.
         // When the scale is too small it will cause internal exceptions while
         // stroking fonts.
-        double currentScale = GeometryUtils.getScale(g.getTransform());
+        AffineTransform curTr = g.getTransform();
+        double currentScale = GeometryUtils.getScale(curTr);
         //System.out.println("currentScale: " + currentScale);
         if (currentScale < 1e-6)
             return;
@@ -652,6 +668,27 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
             r.setRect(x, y, w, h);
         }
 
+        if (hasState(STATE_AUTOMATIC_TEXT_FLIP_ENABLED)) {
+            boolean needsXFlip;
+            boolean needsYFlip;
+            if (curTr.getScaleX() != 0) {
+                needsXFlip = curTr.getScaleX() < 0.0;
+                needsYFlip = curTr.getScaleY() < 0.0;
+            } else {
+                boolean flipAll = !hasState(STATE_AUTOMATIC_TEXT_FLIP_VERTICAL_DOWN);
+                needsXFlip = (curTr.getShearY() < 0.0) ^ flipAll;
+                needsYFlip = (curTr.getShearX() > 0.0) ^ flipAll;
+            }
+            if (needsXFlip || needsYFlip) {
+                double centerX = r.getWidth()*0.5 + r.getX();
+                double centerY = r.getHeight()*0.5 + r.getY();
+
+                g.translate(centerX, centerY);
+                g.scale(needsXFlip ? -1.0 : 1.0, needsYFlip ? -1.0 : 1.0);
+                g.translate(-centerX, -centerY);
+            }
+        }
+
         Rectangle2D textClip = r.getBounds2D();
 
         expandBoundsUnscaled(r);
@@ -674,22 +711,12 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
         // PDF 
         PdfWriter writer = (PdfWriter) g.getRenderingHint(G2DPDFRenderingHints.KEY_PDF_WRITER);
         boolean isRenderingPdf = writer != null;
-        boolean isPdfField = false;
-        String fieldName = null;
-        if (writer != null) {
-               // TODO: replace this hack with proper text field name field
-               fieldName = NodeUtil.getNodeName(this);
-               isPdfField = ( fieldName.equals("approved_by") ||
-                                               fieldName.equals("checked_by") ||
-                                               fieldName.equals("designer name") ||
-                                               fieldName.equals("created_by") );
-        }
+        /// PDF
 
         Color backgroundColor = hasState(STATE_VALID) ? this.backgroundColor : Color.red;
 
         // RENDER
-        if ( !isPdfField ) {
-
+        {
             // Fill background if necessary
             if (backgroundColor != null) {
                 g.setColor(backgroundColor);
@@ -727,10 +754,7 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
 
                 g.setClip(clip);
 
-                // Caret
-                
                 renderCaret(g);
-                
 
             } else {
 
@@ -740,95 +764,7 @@ public class TextNode extends G2DNode implements IDynamicSelectionPainterNode, L
                 }
 
             }
-        } else {
-            // PDF 
-            // TODO: multiline support
-//                             try {
-                           AffineTransform at = g.getTransform();
-                           float height = writer.getPageSize().getHeight();
-                           Rectangle2D rr = textClip;
-       //                  Point2D pt1 = new Point2D.Double(rr.getX(), rr.getY()+rr.getHeight());
-       //                  Point2D pt2 = new Point2D.Double(rr.getX()+rr.getWidth(), rr.getY());
-                           Point2D pt1 = new Point2D.Double(0, 0);
-                           Point2D pt2 = new Point2D.Double(47.f/*+rr.getWidth()*/, -rr.getHeight());
-                           pt1 = at.transform(pt1, pt1);
-                           pt2 = at.transform(pt2, pt2);
-                               Rectangle rectangle = new Rectangle(
-                                               (float) pt1.getX(), 
-                                               height-(float) pt1.getY(), 
-                                               (float) pt2.getX(), 
-                                               height-(float) pt2.getY()); 
-
-                           FontMapper mapper = (FontMapper) g.getRenderingHint(G2DPDFRenderingHints.KEY_PDF_FONTMAPPER);
-//                             FontMetrics fm    = g.getFontMetrics(font);
-
-                               // TODO Oikea leveys
-                               // TODO Uniikki nimi
-                               /*
-                               PdfFormField field = PdfFormField.createTextField(writer, false, false, 20);
-                               field.setFieldName(this.getId().toString());
-                               field.setWidget(rectangle, PdfAnnotation.HIGHLIGHT_NONE);
-                               field.setQuadding(PdfFormField.Q_RIGHT);
-                               field.setFieldFlags(PdfFormField.FF_READ_ONLY);
-                               field.setRotate(90);
-                               writer.addAnnotation(field);
-                               */
-
-
-                               // Signature Field
-                               /*
-                               if (text==null) {
-                                       PdfFormField field = PdfFormField.createSignature(writer);
-                                       field.setWidget(rectangle, PdfAnnotation.HIGHLIGHT_NONE);
-                                       field.setFieldName(fieldName);
-                                       field.setQuadding(PdfFormField.Q_LEFT);
-                                       field.setFlags(PdfAnnotation.FLAGS_PRINT);
-                                       //field.setFieldFlags(PdfFormField.FF_READ_ONLY)
-                                       field.setFieldFlags(PdfFormField.FF_EDIT);
-                                       field.setPage();
-                                       field.setMKBackgroundColor( backgroundColor!=null?Color.WHITE:backgroundColor );
-                                       PdfAppearance tp = PdfAppearance.createAppearance(writer, 72, 48);
-                                       tp.rectangle(rectangle);
-                                       tp.stroke();                            
-                                       field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
-                                       writer.addAnnotation(field);
-                               } else */ 
-                               {
-                                       // Text Field
-                                               try {
-                                               TextField textField = new TextField(writer, rectangle, fieldName);
-                                               textField.setFieldName(fieldName);
-                                               textField.setFont(mapper.awtToPdf(font));
-                                               textField.setBorderStyle(0);
-                                           //textField.setAlignment(Element.ALIGN_LEFT);
-                                           textField.setAlignment(Element.ALIGN_BOTTOM);
-                                           textField.setRotation(90);
-                                       textField.setOptions(TextField.EDIT|TextField.DO_NOT_SPELL_CHECK);
-                                           if ( text!=null ) {
-                                                       textField.setText(text);
-                                           }
-                                           if ( color!=null ) {
-                                               textField.setTextColor(color);
-                                           }
-                                               textField.setBackgroundColor( backgroundColor!=null?Color.WHITE:backgroundColor );
-                                           PdfFormField field = textField.getTextField();
-                                           writer.addAnnotation(field);
-                                               } catch (IOException e) {
-                                                       e.printStackTrace();
-                                               } catch (DocumentException e) {
-                                                       e.printStackTrace();
-                                               }
-                               }
-
-//                             } catch (IOException e) {
-//                                     // TODO Auto-generated catch block
-//                                     e.printStackTrace();
-//                             } catch (DocumentException e) {
-//                                     // TODO Auto-generated catch block
-//                                     e.printStackTrace();
-//                             }
         }
-        /// PDF
 
         g.setClip(clipSave);
 
index 759efbe5634f872717c2701e5adf7ba3739bc156..3f1076b5df48e70047cd4dae8d9531bd494c9d0d 100644 (file)
@@ -7,9 +7,6 @@ import java.awt.geom.Point2D;
 import java.util.ArrayList;
 import java.util.Collection;
 
-import javax.vecmath.Tuple2d;
-import javax.vecmath.Vector2d;
-
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
@@ -247,18 +244,18 @@ public class RouteGraphConnectionSplitter {
         String commonLabel = scheme.generateLabel(graph, diagram);
 
         // Create flags and connect both disconnected ends to them.
-        Vector2d pos1, pos2;
+        Point2D pos1, pos2;
         double theta;
         double flagDist = 3.0;
         if(isHorizontal) {
             theta = 0.0;
-            pos1 = new Vector2d(isectX-flagDist, isectY);
-            pos2 = new Vector2d(isectX+flagDist, isectY);
+            pos1 = new Point2D.Double(isectX-flagDist, isectY);
+            pos2 = new Point2D.Double(isectX+flagDist, isectY);
         }
         else {
             theta = Math.PI*0.5;
-            pos1 = new Vector2d(isectX, isectY-flagDist);
-            pos2 = new Vector2d(isectX, isectY+flagDist);
+            pos1 = new Point2D.Double(isectX, isectY-flagDist);
+            pos2 = new Point2D.Double(isectX, isectY+flagDist);
         }
 
         // Chooses flag directions
@@ -398,8 +395,8 @@ public class RouteGraphConnectionSplitter {
         }
     }
 
-    private AffineTransform getFlagTransform(Tuple2d pos, double theta) {
-        AffineTransform at = AffineTransform.getTranslateInstance(pos.x, pos.y);
+    private AffineTransform getFlagTransform(Point2D pos, double theta) {
+        AffineTransform at = AffineTransform.getTranslateInstance(pos.getX(), pos.getY());
         at.rotate(theta);
         return at;
     }
index 57c1a64e34151a40a728c619cb044551acde3068..a5220f99c8a1ce7678d6b7ead492de954127427d 100644 (file)
@@ -8,9 +8,7 @@ import java.util.Deque;
 import java.util.HashSet;
 import java.util.Set;
 
-import javax.vecmath.Tuple2d;
-import javax.vecmath.Vector2d;
-
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
@@ -129,26 +127,19 @@ public class Splitter {
         // Calculate split position and edge line nearest intersection point
         // ab = normalize( vec(a -> b) )
         // ap = vec(a -> split pos)
-        Vector2d ab = new Vector2d(nearestEdge.getX2() - nearestEdge.getX1(), nearestEdge.getY2() - nearestEdge.getY1());
-        Vector2d ap = new Vector2d(splitCanvasPos.getX() - nearestEdge.getX1(), splitCanvasPos.getY() - nearestEdge.getY1());
-        double theta = Math.atan2(ab.y, ab.x);
-        ab.normalize();
+        Vector2D a = new Vector2D(nearestEdge.getX1(), nearestEdge.getY1());
+        Vector2D ab = new Vector2D(nearestEdge.getX2() - nearestEdge.getX1(), nearestEdge.getY2() - nearestEdge.getY1());
+        Vector2D ap = new Vector2D(splitCanvasPos.getX() - nearestEdge.getX1(), splitCanvasPos.getY() - nearestEdge.getY1());
+        double theta = Math.atan2(ab.getY(), ab.getX());
+        ab = ab.normalize();
 
         // intersection = a + ab*(ap.ab)
-        Vector2d intersection = new Vector2d(ab);
-        intersection.scale(ap.dot(ab));
-        intersection.add(new Vector2d(nearestEdge.getX1(), nearestEdge.getY1()));
+        Vector2D intersection = a.add( ab.scalarMultiply(ap.dotProduct(ab)) );
 
         // Offset flag positions from the intersection point.
-        Vector2d pos1 = new Vector2d(intersection);
-        Vector2d pos2 = new Vector2d(intersection);
-
         // TODO: improve logic for flag positioning, flags just move on the nearest line without boundaries
-        ab.normalize();
-        ab.scale(5);
-        pos2.add(ab);
-        ab.negate();
-        pos1.add(ab);
+        Vector2D pos1 = intersection.subtract(5, ab);
+        Vector2D pos2 = intersection.add(5, ab);
 
         FlagLabelingScheme scheme = DiagramFlagPreferences.getActiveFlagLabelingScheme(graph);
         String commonLabel = scheme.generateLabel(graph, diagram);
@@ -168,8 +159,8 @@ public class Splitter {
         FlagUtil.join(graph, flag1, flag2);
     }
 
-    private AffineTransform getFlagTransform(Tuple2d pos, double theta) {
-        AffineTransform at = AffineTransform.getTranslateInstance(pos.x, pos.y);
+    private AffineTransform getFlagTransform(Vector2D pos, double theta) {
+        AffineTransform at = AffineTransform.getTranslateInstance(pos.getX(), pos.getY());
         at.rotate(theta);
         return at;
     }
index 5b0dfa066478b5362fca8ec6e02492e6ad674fba..52217c3cfcf2b84a6ddc9795d7d13d3f66af80ba 100644 (file)
@@ -150,19 +150,19 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      * A key for storing the current selection within the currently active
      * project for copy/paste implementation.
      */
-    private static final Key               KEY_DIAGRAM_SELECTION              = DiagramSelectionRepresentation.KEY_DIAGRAM_SELECTION;
+    private static final Key              KEY_DIAGRAM_SELECTION              = DiagramSelectionRepresentation.KEY_DIAGRAM_SELECTION;
 
     private static final boolean          DEBUG                              = false;
     private static final boolean          DEBUG_SELECTION_UPDATE             = false;
 
     public static final int               COPY_GHOSTING_PAINT_PRIORITY       = 600;
 
-    private static final int              HIGHLIGHT_PAINT_PRIORITY           = 500;
+    protected static final int            HIGHLIGHT_PAINT_PRIORITY           = 500;
 
     @Dependency
-    private Selection                     sel;
+    protected Selection                   sel;
     @Dependency
-    private MouseUtil                     mouseUtil;
+    protected MouseUtil                   mouseUtil;
 
     protected final IStatusLineManager    statusLine;
     protected final CopyPasteStrategy     strategy;
@@ -205,7 +205,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      */
     protected boolean                     hasFocus                           = false;
 
-    private AbstractCanvasParticipant     highlightMode                      = null;
+    protected AbstractCanvasParticipant   highlightMode                      = null;
     private IProject                      observedProject                    = null;
 
     /**
@@ -375,7 +375,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         return DiagramSelection.EMPTY;
     }
 
-    private DiagramSelection getProjectSelection() {
+    protected DiagramSelection getProjectSelection() {
         IProject p = peekProject();
         if (p == null)
             return DiagramSelection.EMPTY;
@@ -383,12 +383,12 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         return ds != null ? ds : DiagramSelection.EMPTY;
     }
 
-    void setDiagramSelection(DiagramSelection selection) {
+    protected void setDiagramSelection(DiagramSelection selection) {
         setProjectSelection(selection);
         strategy.copyToClipboard(selection);
     }
 
-    void setProjectSelection(DiagramSelection selection) {
+    protected void setProjectSelection(DiagramSelection selection) {
         assert selection != null;
         IProject p = getProject();
         if (p == null)
@@ -399,7 +399,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         p.setHint(KEY_DIAGRAM_SELECTION, selection);
     }
 
-    private void removeProjectSelection() {
+    protected void removeProjectSelection() {
         setProjectSelection(DiagramSelection.EMPTY);
         removeHighlight();
         clearSG();
@@ -473,7 +473,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         return false;
     }
 
-    boolean initiateCopy(boolean cut) {
+    protected boolean initiateCopy(boolean cut) {
         //System.out.println("INITIATING COPY");
         int selectionId = 0;
 
@@ -576,7 +576,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
             message(null);
             return false;
         }
-        
+
         TimeLogger.resetTimeAndLog(getClass(), "paste");
 
         ElementObjectAssortment ea = ds.getAssortment();
@@ -685,7 +685,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         }
     }
 
-    private String fixAssortment(ElementAssortment ea, boolean cut) {
+    protected String fixAssortment(ElementAssortment ea, boolean cut) {
         Topology diagramTopology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);
         List<Connection> conns = new ArrayList<Connection>();
 
@@ -823,7 +823,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      * @param ea
      * @return
      */
-    private void pruneAssortment(ElementAssortment ea, boolean cut) {
+    protected void pruneAssortment(ElementAssortment ea, boolean cut) {
         // Edges and branch points are never copied as such.
         // They are always included as parts of copied connections.
         // Edges can never be transformed or modified in any way as such,
@@ -872,7 +872,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      * @param e
      * @return
      */
-    private static boolean isConnectionOrEdge(IElement e) {
+    protected static boolean isConnectionOrEdge(IElement e) {
         ElementClass ec = e.getElementClass();
         return ec.containsClass(ConnectionHandler.class)|| ec.containsClass(BendsHandler.class);
     }
@@ -881,7 +881,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      * @param e
      * @return
      */
-    private static boolean isMoveable(IElement e) {
+    protected static boolean isMoveable(IElement e) {
         ElementClass ec = e.getElementClass();
         return ec.containsClass(Move.class) && ec.containsClass(Transform.class);
     }
@@ -891,7 +891,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
      * @return <code>null</code> if a point of reference cannot be determined
      *         for the specified selection.
      */
-    private Point2D getCopyStartPos(Set<IElement> ss) {
+    protected Point2D getCopyStartPos(Set<IElement> ss) {
 //        MouseInfo mi = mouseUtil.getMouseInfo(0);
 //        if (mi != null) {
 //            return (Point2D) mi.canvasPosition.clone();
@@ -1090,11 +1090,11 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         return ghostNode.addNode(id, clazz);
     }
 
-    private boolean hasHighlight() {
+    protected boolean hasHighlight() {
         return highlightMode != null;
     }
 
-    private void removeHighlight() {
+    protected void removeHighlight() {
         if (isRemoved())
             return;
         assert getContext().getThreadAccess().currentThreadAccess();
@@ -1111,7 +1111,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         return (e.stateMask & MouseEvent.CTRL_MASK) != 0;
     }
 
-    void selectedMessage(DiagramSelection ds) {
+    protected void selectedMessage(DiagramSelection ds) {
         int size = ds.getOriginalElements().size();
         StringBuilder sb = new StringBuilder();
         if (size == 0) {
@@ -1133,7 +1133,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         message(sb.toString());
     }
 
-    void message(final String message) {
+    protected void message(final String message) {
         if (statusLine == null)
             return;
         swtExec(new Runnable() {
@@ -1145,7 +1145,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         });
     }
 
-    void error(final String message) {
+    protected void error(final String message) {
         if (statusLine == null)
             return;
         swtExec(new Runnable() {
@@ -1156,7 +1156,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
         });
     }
 
-    void swtExec(Runnable r) {
+    protected void swtExec(Runnable r) {
         ThreadUtils.asyncExec(SWTThread.getThreadAccess(Display.getDefault()), r);
     }
 
@@ -1289,7 +1289,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant {
                                     graph.claim(resource, L0X.ObtainsProperty1, null, template);
                                 }
                             }
-                            
+
                         }
                     });
                 }
index 0f243db4816d72976fee02048a961531a21c6677..c8995f4c1f4777be79311bc0d502616af534f147 100644 (file)
@@ -1,8 +1,6 @@
 package org.simantics.diagram.handler;
 
 import static org.simantics.diagram.handler.Paster.ComposedCutProcedure.compose;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
 
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
@@ -14,6 +12,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
+import java.util.function.BiFunction;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
@@ -62,9 +61,11 @@ import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.structural2.modelingRules.CPTerminal;
 import org.simantics.structural2.modelingRules.ConnectionJudgement;
 import org.simantics.structural2.modelingRules.IConnectionPoint;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.simantics.utils.datastructures.map.Tuple;
 
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
 /**
  * @author Tuukka Lehtonen
  */
@@ -273,7 +274,7 @@ public class Paster {
         return noParentElementReturnValue;
     }
 
-    private void cut() throws Exception {
+    protected void cut() throws Exception {
         final GraphLayerManager glm = targetContext.get(GraphSynchronizationHints.GRAPH_LAYER_MANAGER);
 
         final THashSet<Resource> cutElements = new THashSet<Resource>();
@@ -688,10 +689,10 @@ public class Paster {
      * Diagram mapping will have problems and potentially break the
      * configuration if the type is not the same as in the source.
      */
-    BinaryFunction<StatementEvaluation, ReadGraph, Statement> statementAdvisor =
-            new BinaryFunction<StatementEvaluation, ReadGraph, Statement>() {
+    BiFunction<ReadGraph, Statement, StatementEvaluation> statementAdvisor =
+            new BiFunction<ReadGraph, Statement, StatementEvaluation>() {
         @Override
-        public StatementEvaluation call(ReadGraph graph, Statement stm) {
+        public StatementEvaluation apply(ReadGraph graph, Statement stm) {
             if (DIA.HasFlagType.equals(stm.getPredicate()))
                 return StatementEvaluation.INCLUDE;
             return StatementEvaluation.USE_DEFAULT;
@@ -747,7 +748,7 @@ public class Paster {
         }
     };
 
-    private void copy() throws Exception {
+    protected void copy() throws Exception {
         nodeMap = new NodeMap();
         
         CommonDBUtils.selectClusterSet(graph, targetDiagram);
@@ -1359,5 +1360,8 @@ public class Paster {
     public NodeMap getNodeMap() {
         return nodeMap;
     }
-
+    
+    protected PasteOperation getOperation() {
+       return op;
+    }
 }
index 7d172318bf1b8561c009f2ef55086e62ee7037fc..4ec3258a7822554f228ccbf0ddd83af6b8dce909 100644 (file)
@@ -987,18 +987,20 @@ public class SymbolLibraryComposite extends Composite {
         final boolean expanded = grp.getExpanded();
         final boolean visible = grp.getVisible();
         final boolean filterChanged = !objectEquals(filter, lastFilter);
+        final ISymbolGroup symbolGroup = (ISymbolGroup) grp.getData(SymbolLibraryKeys.KEY_GROUP);
+        final boolean filterMatchesGroup = filter != null && filter.select(viewer, null, symbolGroup);
 
         // Find out how much data would be shown with the new filter.
-        viewer.setFilter(filter);
+        viewer.setFilter(filterMatchesGroup ? null : filter);
         Object[] elements = viewer.getFilteredElements();
 
-        ISymbolGroup symbolGroup = (ISymbolGroup) grp.getData(SymbolLibraryKeys.KEY_GROUP);
-        boolean filterMatchesGroup = filter != null && filter.select(viewer, null, symbolGroup);
         boolean shouldBeVisible = !groupFiltered && (elements.length > 0 || filterMatchesGroup);
         boolean shouldBeExpanded = shouldBeVisible && (filter != null || userExpanded);
 
-//        System.out.format("%40s: visible/should be = %5s %5s,  expanded/user expanded/should be = %5s %5s %5s\n",
+//        System.out.format("%40s: filterMatchesGroup(%s) = %s, visible/should be = %5s %5s,  expanded/user expanded/should be = %5s %5s %5s\n",
 //                grp.getText(),
+//                symbolGroup.getName(),
+//                String.valueOf(filterMatchesGroup),
 //                String.valueOf(visible),
 //                String.valueOf(shouldBeVisible),
 //                String.valueOf(expanded),
index 60d4c56aeaa54d9c5d0559dcea7b189d188e6a06..61d09acdd3cb18981d53c67e9300d255a3fc23d6 100644 (file)
@@ -15,6 +15,7 @@ import gnu.trove.map.hash.THashMap;
 
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.Binding;
@@ -44,7 +45,6 @@ import org.simantics.diagram.synchronization.SynchronizationHints;
 import org.simantics.graph.db.TransferableGraphs;
 import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.layer0.Layer0;
-import org.simantics.utils.datastructures.BinaryFunction;
 
 /**
  * This class contains utility methods for the basic cut/copy operations
@@ -223,7 +223,7 @@ public class CopyAdvisorUtil {
      * @return the copied resource
      * @throws DatabaseException
      */
-    public static Resource copy(WriteGraph graph, Resource source, BinaryFunction<Boolean, ReadGraph, Statement> advisor) throws DatabaseException {
+    public static Resource copy(WriteGraph graph, Resource source, BiFunction<ReadGraph, Statement, Boolean> advisor) throws DatabaseException {
         return copy(graph, source, 0, advisor, new THashMap<Object, Object>());
     }
 
@@ -238,11 +238,11 @@ public class CopyAdvisorUtil {
      * @return
      * @throws DatabaseException
      */
-    public static Resource copy(WriteGraph graph, Resource source, BinaryFunction<Boolean, ReadGraph, Statement> advisor, Map<Object, Object> copyMap) throws DatabaseException {
+    public static Resource copy(WriteGraph graph, Resource source, BiFunction<ReadGraph, Statement, Boolean> advisor, Map<Object, Object> copyMap) throws DatabaseException {
         return copy(graph, source, 0, advisor, copyMap);
     }
 
-    private static Resource copy(WriteGraph graph, Resource source, int level, BinaryFunction<Boolean, ReadGraph, Statement> advisor, Map<Object, Object> copyMap) throws DatabaseException {
+    private static Resource copy(WriteGraph graph, Resource source, int level, BiFunction<ReadGraph, Statement, Boolean> advisor, Map<Object, Object> copyMap) throws DatabaseException {
         if (DEBUG_COPY)
             System.out.println("[" + level + "] CopyAdvisorUtil.copy(" + NameUtils.getSafeName(graph, source) + ", advisor=" + advisor + ")");
 
@@ -320,7 +320,7 @@ public class CopyAdvisorUtil {
                 }
             } else {
                 if (advisor != null) {
-                    Boolean result = advisor.call(graph, stm);
+                    Boolean result = advisor.apply(graph, stm);
                     if (Boolean.TRUE.equals(result)) {
                         // Don't clone the object, just add relation to the same object.
                         if (inverse != null)
@@ -363,7 +363,7 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException
      */
     public static Resource copy2(WriteGraph graph, Resource source,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor) throws DatabaseException {
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor) throws DatabaseException {
         return copy2(graph, source, 0, advisor, new THashMap<Object, Object>());
     }
 
@@ -379,13 +379,13 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException 
      */
     public static Resource copy2(WriteGraph graph, Resource source,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor, Map<Object, Object> copyMap)
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap)
             throws DatabaseException {
         return copy2(graph, source, 0, advisor, copyMap);
     }
 
     private static Resource copy2(final WriteGraph graph, final Resource source, final int level,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor, Map<Object, Object> copyMap)
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap)
     throws DatabaseException {
         if (DEBUG_COPY)
             System.out.println("[" + level + "] CopyAdvisorUtil.copy(" + NameUtils.getSafeName(graph, source) + ", advisor=" + advisor + ")");
@@ -536,7 +536,7 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException
      */
     public static Resource copy3(WriteGraph graph, Resource source, Resource model,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor) throws DatabaseException {
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor) throws DatabaseException {
         String modelURI = graph.getURI(model);
         return copy3(graph, modelURI, source, 0, advisor, new THashMap<Object, Object>());
     }
@@ -554,13 +554,13 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException
      */
     public static Resource copy3(WriteGraph graph, Resource source, Resource model,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor, Map<Object, Object> copyMap) throws DatabaseException {
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap) throws DatabaseException {
         String modelURI = graph.getURI(model);
         return copy3(graph, modelURI, source, 0, advisor, copyMap);
     }
 
     private static Resource copy3(WriteGraph graph, String modelURI, Resource source, int level,
-            BinaryFunction<StatementEvaluation, ReadGraph, Statement> advisor, Map<Object, Object> copyMap)
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap)
     throws DatabaseException {
         if (DEBUG_COPY)
             System.out.println("[" + level + "] CopyAdvisorUtil.copy(" + NameUtils.getSafeName(graph, source) + ", advisor=" + advisor + ")");
@@ -698,10 +698,10 @@ public class CopyAdvisorUtil {
         return copy;
     }
 
-    protected static StatementEvaluation evaluate(ReadGraph graph, Statement stm, BinaryFunction<StatementEvaluation, ReadGraph, Statement> tester) {
+    protected static StatementEvaluation evaluate(ReadGraph graph, Statement stm, BiFunction<ReadGraph, Statement, StatementEvaluation> tester) {
         if (tester == null)
             return StatementEvaluation.USE_DEFAULT;
-        return tester.call(graph, stm);
+        return tester.apply(graph, stm);
     }
 
     /**
index c321d212ce1dec3ce2362c7fcce3f2b035766e45..51f83d20b95b56c28aed8e4e5b7dff941ea53dd0 100644 (file)
Binary files a/bundles/org.simantics.document.base.ontology/graph.tg and b/bundles/org.simantics.document.base.ontology/graph.tg differ
index 5397d24db2e0fd080cac9cb5315252a58a9ec03a..517ce7f3b4a44b80eaa8288315e283edfd80c369 100644 (file)
@@ -9,6 +9,7 @@ Require-Bundle: org.simantics.layer0,
  org.simantics.scenegraph.ontology;bundle-version="1.0.0",
  org.simantics.viewpoint.ontology;bundle-version="1.0.0",
  org.simantics.selectionview.ontology;bundle-version="1.1.0",
- org.simantics.graphfile.ontology;bundle-version="0.1.0"
+ org.simantics.graphfile.ontology;bundle-version="0.1.0",
+ org.simantics.action.ontology;bundle-version="1.1.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.simantics.document
index aadabaa9a92d5782509edce10315771b1e9dbcf2..94f3d05181d30bad5872617c811080b9a5861860 100644 (file)
Binary files a/bundles/org.simantics.document.ontology/graph.tg and b/bundles/org.simantics.document.ontology/graph.tg differ
index e006a5fd8a141157a7f5e7687a1b79a030f617c6..b35002d40c3aa9fbad91e1c94b30dbc97c4a11d8 100644 (file)
@@ -3,6 +3,7 @@ L0X = <http://www.simantics.org/Layer0X-1.1>
 SG = <http://www.simantics.org/Scenegraph-1.1>
 SEL = <http://www.simantics.org/SelectionView-1.2>
 GF = <http://www.simantics.org/GraphFile-0.1>
+ACT = <http://www.simantics.org/Action-1.1>
 
 DOC = <http://www.simantics.org/Document-1.2> : L0.Ontology
     @L0.new
@@ -158,4 +159,8 @@ DOC.PlainTextDocument <T DOC.Document
 
 
 DOC.DocumentLibrary <T L0.Library
+
+DOC.Actions : L0.Library
+
+DOC.Actions.ImportFileDocument : ACT.Action
    
\ No newline at end of file
index 2bca437a26934bbbd1be4c85eb835e34b1dd2cc1..d98c2e5b065eea2a940d8ae7132b190f3c22d76e 100644 (file)
@@ -10,6 +10,8 @@ import org.simantics.db.service.QueryControl;
 
 public class DocumentResource {
     
+    public final Resource Actions;
+    public final Resource Actions_ImportFileDocument;
     public final Resource Document;
     public final Resource DocumentLibrary;
     public final Resource DocumentSettings;
@@ -91,6 +93,8 @@ public class DocumentResource {
     public final Resource documentSettings_Inverse;
         
     public static class URIs {
+        public static final String Actions = "http://www.simantics.org/Document-1.2/Actions";
+        public static final String Actions_ImportFileDocument = "http://www.simantics.org/Document-1.2/Actions/ImportFileDocument";
         public static final String Document = "http://www.simantics.org/Document-1.2/Document";
         public static final String DocumentLibrary = "http://www.simantics.org/Document-1.2/DocumentLibrary";
         public static final String DocumentSettings = "http://www.simantics.org/Document-1.2/DocumentSettings";
@@ -182,6 +186,8 @@ public class DocumentResource {
     }
     
     public DocumentResource(ReadGraph graph) {
+        Actions = getResourceOrNull(graph, URIs.Actions);
+        Actions_ImportFileDocument = getResourceOrNull(graph, URIs.Actions_ImportFileDocument);
         Document = getResourceOrNull(graph, URIs.Document);
         DocumentLibrary = getResourceOrNull(graph, URIs.DocumentLibrary);
         DocumentSettings = getResourceOrNull(graph, URIs.DocumentSettings);
index 7a59a14610284d988378e633c1e5773063ff2f6b..9bf10fb3a67d4ad2c1dc7fb23a4bc56b81be9652 100644 (file)
@@ -3,4 +3,9 @@ package org.simantics.document.server.io;
 public interface ITreeTableCell extends ITableCell {
     
        int getParent();
+       
+        Object getData();
+
+     boolean isEditable();
+     
 }
index 8913645a9946c3f4884fd4e8c5ae9f028afaea1a..558ee320459e519823852eac43d654763e90906f 100644 (file)
@@ -13,6 +13,7 @@
 package org.simantics.document.server.io;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -343,4 +344,72 @@ public class JSONObjectUtils {
         else
             return Collections.<IListItem>emptyList();
     }
+    
+    @SuppressWarnings("unchecked")
+    public static Collection<ITreeTableCell> getTreeTableCell(IJSONObject object) {
+        try {
+            Object treeTableCells = object.getValue("tableCells");
+            if (treeTableCells instanceof String) {
+                String tableCellsS = (String) treeTableCells;
+                if (tableCellsS.length() == 0)
+                    return Collections.emptyList();
+            }
+            if (treeTableCells != null) {
+                return (List<ITreeTableCell>) treeTableCells;
+            } else {
+                return Collections.emptyList();
+            }
+        } catch (ClassCastException e) {
+            e.printStackTrace();
+        }
+        return Collections.emptyList();
+    }
+
+    public static final boolean equalObjects(Object oldValue, Object newValue) {
+       if (newValue != null) {
+               if (newValue.getClass().isArray()) {
+                       return arrayEquals(newValue, oldValue);
+               } else {
+                       return newValue.equals(oldValue);
+               }
+       } else
+               return oldValue == null;
+    }
+
+    
+       /**
+        * @param av1 an array (guaranteed)
+        * @param av2 any object
+        * @return <code>true</code> if the two arrays are equal
+        */
+       private static final boolean arrayEquals(Object av1, Object av2) {
+               if (av2 == null)
+                       return false;
+               Class<?> c1 = av1.getClass().getComponentType();
+               Class<?> c2 = av2.getClass().getComponentType();
+               if (c2 == null || !c1.equals(c2))
+                       return false;
+               boolean p1 = c1.isPrimitive();
+               boolean p2 = c2.isPrimitive();
+               if (p1 != p2)
+                       return false;
+               if (!p1)
+                       return Arrays.equals((Object[]) av1, (Object[]) av2);
+               if (boolean.class.equals(c1))
+                       return Arrays.equals((boolean[]) av1, (boolean[]) av2);
+               else if (byte.class.equals(c1))
+                       return Arrays.equals((byte[]) av1, (byte[]) av2);
+               else if (int.class.equals(c1))
+                       return Arrays.equals((int[]) av1, (int[]) av2);
+               else if (long.class.equals(c1))
+                       return Arrays.equals((long[]) av1, (long[]) av2);
+               else if (float.class.equals(c1))
+                       return Arrays.equals((float[]) av1, (float[]) av2);
+               else if (double.class.equals(c1))
+                       return Arrays.equals((double[]) av1, (double[]) av2);
+               throw new RuntimeException("Unsupported objects for equality testing ." + av1 + " vs. " + av2);
+               
+       }
+    
+    
 }
index 23896814224bdeed738e03fb32723c466fc5d367..fa83a224acfc2d7076af4417e2f2e181680e93e7 100644 (file)
@@ -21,6 +21,13 @@ importJava "org.simantics.document.server.io.ITreeTableCell" where
 
 importJava "org.simantics.document.server.io.IFont" where
     data IFont
+    
+    @JavaName getFamily
+    fontFamily :: IFont -> <Proc> Maybe String
+    @JavaName getStyle
+    fontStyle :: IFont -> <Proc> Maybe String
+    @JavaName getHeight
+    fontHeight :: IFont -> <Proc> Integer
 
 importJava "org.simantics.document.server.io.IColor" where
     data IColor
index fb597cc1cac5634dce3932cbda5b52645e80d882..332f21fb25d0649a359ca3152f1b44fc3807cee3 100644 (file)
Binary files a/bundles/org.simantics.document.swt.ontology/graph.tg and b/bundles/org.simantics.document.swt.ontology/graph.tg differ
index e1ef059472784e15937b2adf7600326cd571f634..dc11fa0e32ce64899ea375bfdb7b3f81bcc10835 100644 (file)
@@ -6,6 +6,7 @@ Bundle-Version: 1.1.0.qualifier
 Bundle-Vendor: Semantum Oy
 Require-Bundle: org.simantics.layer0,
  org.simantics.views.ontology;bundle-version="1.1.0",
+ org.simantics.views.text.ontology;bundle-version="1.0.0",
  org.simantics.modeling.ontology;bundle-version="1.1.0",
  org.simantics.scenegraph.ontology;bundle-version="1.0.0",
  org.simantics.document.ontology;bundle-version="1.1.0",
index 66fea40388122bceab20c2c2a1b2f110e3a5154e..8ef6e047fd28d54ce23586151a80cfc152bfcecc 100644 (file)
Binary files a/bundles/org.simantics.document.ui.ontology/graph.tg and b/bundles/org.simantics.document.ui.ontology/graph.tg differ
index 3ac065d5e5ef78299553b91710f9538720db247c..b06a314a38fa29ac97f93c484fd7d42b434e91d2 100644 (file)
@@ -1,5 +1,6 @@
 L0 = <http://www.simantics.org/Layer0-1.1>
 VIEWS = <http://www.simantics.org/Views-1.2>
+TEXTVIEWS = <http://www.simantics.org/TextViews-1.0>
 SG = <http://www.simantics.org/Scenegraph-1.1>
 DOC = <http://www.simantics.org/Document-1.2>
 ACT = <http://www.simantics.org/Action-1.1>
@@ -40,11 +41,6 @@ UI.WikitextContribution.View : VIEWS.Composite
     @L0.list
       _ : VIEWS.Composite
         VIEWS.Composite.layout _ : VIEWS.RowLayout
-          //VIEWS.RowLayout.type VIEWS.Control.Style.Constant.Horizontal
-          //VIEWS.RowLayout.spacing 0
-          //VIEWS.RowLayout.justify true
-          //VIEWS.RowLayout.pack true
-          //VIEWS.RowLayout.wrap true
         VIEWS.Control.layoutData _ : VIEWS.GridLayout.GridData
           VIEWS.GridLayout.GridData.horizontalGrab true
         SG.Node.children _ : L0.List
@@ -159,7 +155,7 @@ UI.WikitextContribution.View : VIEWS.Composite
         VIEWS.Composite.layout _ : VIEWS.GridLayout
         SG.Node.children _ : L0.List
           @L0.list
-            UI.WikitextContribution.View.Text : VIEWS.StyledText
+            UI.WikitextContribution.View.Text : TEXTVIEWS.MarkupSourceViewer
               @VIEWS.Control.style4 VIEWS.Control.Style.Constant.Multi VIEWS.Control.Style.Constant.Border VIEWS.Control.Style.Constant.VScroll VIEWS.Control.Style.Constant.HScroll
               VIEWS.TextContainer.text UI.Functions.selectedDocumentPart : L0.Function
                 L0.HasValueType "String"
@@ -200,13 +196,6 @@ UI.Sash : VIEWS.SashForm
   VIEWS.SashForm.orientation VIEWS.SashForm.Vertical
   SG.Node.children _ : L0.List
     @L0.list
-//      UI.Scroll : VIEWS.ScrolledComposite
- //       VIEWS.Control.layoutData
- //         _ : VIEWS.GridLayout.GridData
- //           VIEWS.GridLayout.GridData.horizontalGrab true
- //           VIEWS.GridLayout.GridData.verticalGrab true
- //       SG.Node.children _ : L0.List
- //         @L0.list
       UI.Browser : VIEWS.Browser
         VIEWS.Control.layoutData
           _ : VIEWS.GridLayout.GridData
index 5d0115b16f2e9036ab848cd989c629be03ddce2d..fa2877b11b34c5c98461e973b380b4932a2f169c 100644 (file)
@@ -7,6 +7,7 @@ Bundle-Activator: org.simantics.document.ui.Activator
 Bundle-Vendor: Semantum Oy
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
+ org.simantics.views;bundle-version="1.1.0",
  org.simantics.views.swt;bundle-version="1.0.0",
  org.simantics.document.ontology;bundle-version="1.0.0",
  org.simantics.document.ui.ontology;bundle-version="1.0.0",
@@ -14,12 +15,9 @@ Require-Bundle: org.eclipse.ui,
  org.simantics.modeling.ontology;bundle-version="1.1.0",
  org.simantics.scenegraph.ontology;bundle-version="1.0.0",
  org.simantics.document;bundle-version="1.0.0",
- org.eclipse.mylyn.wikitext.mediawiki.core;bundle-version="1.5.2",
- org.eclipse.mylyn.wikitext.core;bundle-version="1.5.1",
  org.simantics.wiki.ui;bundle-version="1.1.0",
  org.simantics.browsing.ui;bundle-version="1.1.0",
  org.simantics.selectionview;bundle-version="1.0.0",
- org.simantics.views;bundle-version="1.1.0",
  org.simantics.utils.thread.swt;bundle-version="1.1.0",
  org.simantics.browsing.ui.model;bundle-version="1.0.0";visibility:=reexport,
  org.simantics.graphfile;bundle-version="0.1.0",
@@ -29,7 +27,8 @@ Require-Bundle: org.eclipse.ui,
  org.simantics.annotation.ontology;bundle-version="1.0.0",
  org.simantics.annotation.ui;bundle-version="1.0.0",
  org.eclipse.ui.editors;bundle-version="3.9.0",
- org.eclipse.jface.text
+ org.eclipse.jface.text,
+ org.slf4j.api;bundle-version="1.7.2"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ActivationPolicy: lazy
 Export-Package: org.simantics.document.ui,
index 2493b1c2c1d58b501858d653ce256f30860e9e16..6cd9ccebb547e1465897724880824d8aac32d110 100644 (file)
@@ -15,20 +15,20 @@ importJava "org.simantics.document.ui.actions.ExportDocumentFile" where
     exportDocument :: Resource -> String -> <Proc> ()
 
 documentsFolders :: Model -> <ReadGraph> [Resource]
-documentsFolders model = recurse DOCUMENT.DocumentLibrary (toResource model)
+documentsFolders model = recurse DOCUMENT.DocumentLibrary model
   where
     recurse t r = do
-        cs = resourceChildrenOf r 
+        cs = children r 
         libraries = filter isLibrary cs
         libraryGrp = filter (not . isLibrary) cs
         libraries + concatMap (recurse t) libraryGrp
     isLibrary r = isInstanceOf r DOCUMENT.DocumentLibrary
 
 documents :: Model -> <ReadGraph> [Resource]
-documents model = recurse DOCUMENT.Document (toResource model)
+documents model = recurse DOCUMENT.Document model
   where
     recurse t r = do
-        cs = resourceChildrenOf r 
+        cs = children r 
         documents = filter isDocument cs
         documentFolder = filter (not . isDocument) cs
         documents + concatMap (recurse t) documentFolder
index ffb874f6fb00957a775ccecc455c6050910a70da..b5fbe0adddad16de16acc3f5694caf847aa1a9a5 100644 (file)
@@ -19,6 +19,7 @@ import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.AddDocumentAction;
 import org.simantics.document.DocumentResource;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.datastructures.Callback;
index 824a0b5fbb8de26ebe6d6a138049809053dfa96a..5ed7a1a2bcf0926fb20a5fc417bafc86e877da49 100644 (file)
@@ -21,6 +21,7 @@ import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
 import org.simantics.db.exception.ServiceException;
+import org.simantics.document.AddDocumentAction;
 import org.simantics.document.DocumentResource;
 import org.simantics.document.ui.dialogs.UrlDetailDialog;
 import org.simantics.layer0.Layer0;
index e118e9988012a32f442c14c2949a89c6142cb0e2..3956a5923bdd7b377c71ac5d14562ee2c4758d93 100644 (file)
@@ -26,8 +26,8 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.ActionFactory;
+import org.simantics.document.FileDocumentUtil;
 import org.simantics.document.ui.Activator;
-import org.simantics.document.ui.graphfile.FileDocumentUtil;
 import org.simantics.graphfile.util.GraphFileUtil;
 
 /**
index 3c8e0af303151f21ebacc7cdf20fcb6c469c57c5..88eb503f5a56e28b0f65c2381a1dae3618138a43 100644 (file)
@@ -25,8 +25,8 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.ActionFactory;
+import org.simantics.document.FileDocumentUtil;
 import org.simantics.document.ui.Activator;
-import org.simantics.document.ui.graphfile.FileDocumentUtil;
 
 /**
  * Action for importing files as documents.
index 7235f55f09382b854d3dada7ca025df36610f763..42a0a7c94fa8bd9476b069a73bf00698796fd8e9 100644 (file)
@@ -21,8 +21,9 @@ import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.AddDocumentAction;
+import org.simantics.document.FileDocumentUtil;
 import org.simantics.document.ui.dialogs.FileDetailDialog;
-import org.simantics.document.ui.graphfile.FileDocumentUtil;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.datastructures.Callback;
 import org.simantics.utils.ui.ExceptionUtils;
index 76b5abe95c48559e3a384506b4ad5e3b2582e2a6..effe30cd9b51c0ead4d1b7e97105d48c93fd0838 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Association for Decentralized Information Management in
+ * Copyright (c) 2012, 2017 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
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - (#7066) introducing logger & refactoring
  *******************************************************************************/
 package org.simantics.document.ui.function;
 
@@ -38,7 +39,6 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.request.UnaryRead;
 import org.simantics.db.common.request.WriteRequest;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.common.utils.RequestUtil;
 import org.simantics.db.exception.DatabaseException;
@@ -68,10 +68,14 @@ import org.simantics.ui.workbench.ResourceEditorInput2;
 import org.simantics.ui.workbench.action.DefaultActions;
 import org.simantics.utils.threads.SWTThread;
 import org.simantics.utils.ui.workbench.WorkbenchUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 public class All {
 
+       private static final Logger LOGGER = LoggerFactory.getLogger(All.class);
+
        private static boolean createDocument(WriteGraph graph, Resource resource, Resource model) throws DatabaseException {
 
                Layer0 L0 = Layer0.getInstance(graph);
@@ -187,6 +191,7 @@ public class All {
                                                                if(document == null) return;
                                                                
                                                                RemoverUtil.remove(graph, document);
+                                                               graph.markUndoPoint();
                                                                
                                                        }
                                                
@@ -318,12 +323,12 @@ public class All {
 
                                                @Override
                                                public void perform(WriteGraph graph) throws DatabaseException {
-                                                       
                                                        Variable selection = resolveEditSelection(graph, context, "..../Scroll/Browser#edited");
-                                                       if (selection != null)
+                                                       if (selection != null) {
                                                            selection.setValue(graph, (String)value, Bindings.STRING);
-                                                       else {
-                                                               System.err.println("no selection for resource : " + resource + ", Variable context : " + context + ", value : " + value);
+                                                               graph.markUndoPoint();
+                                                       } else {
+                                                               LOGGER.error("No selection for resource : " + resource + ", Variable context : " + context + ", value : " + value);
                                                        }
                                                }
                                                
@@ -743,19 +748,12 @@ public class All {
                                        String editorId = CSSEditor.EDITOR_ID;
                                RVI rvi = null;
 
-                               PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
-                                       
-                                   @Override
-                                   public void run() {
-
-                                                   try {
-                                                                       WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, root, root, rvi));
-                                                               } catch (PartInitException e) {
-                                                                       Logger.defaultLogError(e);
-                                                               }
-                                       
+                               PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
+                                   try {
+                                       WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, root, root, rvi));
+                                   } catch (PartInitException e) {
+                                       LOGGER.error("Failed to open CSS editor for root " + root, e);
                                    }
-                                   
                                });
 
                                        }
index abd95948d2c032f6d05968de16709f8f0ccd6f68..0959ae9f854b9ba3aa900acc84143f8c26b1466a 100644 (file)
@@ -5,7 +5,7 @@ import java.io.File;
 import org.eclipse.jface.wizard.IWizardPage;
 import org.eclipse.jface.wizard.Wizard;
 import org.simantics.db.Resource;
-import org.simantics.document.ui.graphfile.FileDocumentUtil;
+import org.simantics.document.FileDocumentUtil;
 
 public abstract  class FileDocumentImportWizard extends Wizard{
        
index f20e8863957c8e6b45508a73a79541069f36a9d4..44e4db9dc3ea33a543570ce017539a416bea8078 100644 (file)
@@ -13,7 +13,9 @@ Require-Bundle: org.simantics;bundle-version="1.0.0",
  org.simantics.wiki.ui;bundle-version="1.1.0",
  org.simantics.export.core;bundle-version="1.0.0",
  org.simantics.utils.ui;bundle-version="1.1.0",
- org.simantics.image2.ontology;bundle-version="1.2.0"
+ org.simantics.image2.ontology;bundle-version="1.2.0",
+ org.simantics.graphfile.ontology;bundle-version="0.1.0",
+ org.simantics.graphfile;bundle-version="0.1.0"
 Export-Package: org.simantics.document,
  org.simantics.document.export,
  org.simantics.document.function,
index b5065445af809312f81b4ecdd19f11322d9c0a93..20b594d6f1f9a89e9bcb5bfbc7d7abb8e7d5463e 100644 (file)
@@ -17,6 +17,9 @@ import org.osgi.framework.BundleContext;
 
 public class Activator implements BundleActivator {
 
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.simantics.document"; //$NON-NLS-1$
+
        private static BundleContext context;
 
        static BundleContext getContext() {
diff --git a/bundles/org.simantics.document/src/org/simantics/document/AddDocumentAction.java b/bundles/org.simantics.document/src/org/simantics/document/AddDocumentAction.java
new file mode 100644 (file)
index 0000000..8012c4d
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.document;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.adapter.ActionFactory;
+
+/**
+ * Abstract base class for adding documents.
+ * 
+ * If import target is an document, a new version of a document is created.
+ * 
+ * Document version creation has two modes:
+ * FLAT: new version is added to the same library as the old document.
+ * TREE: new version replaces the old document in the library, and old document is moved under the new document.
+ * 
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public abstract class AddDocumentAction implements ActionFactory {
+       
+       private Resource relation;
+       
+       public AddDocumentAction(ReadGraph graph, String relationUri) throws DatabaseException {
+               relation = graph.getResource(relationUri);
+       }
+       
+
+       protected Resource getRelation() {
+               return relation;
+       }
+       
+       protected void linkDocument(WriteGraph graph, Resource target, Resource newDocument) throws DatabaseException{
+               DocumentResource doc = DocumentResource.getInstance(graph);
+       
+               if (graph.isInstanceOf(target, doc.Document)) {
+                       // adding a new revision
+                       DocumentVersionUtils.createNewVersion(graph, target, newDocument, relation);
+                       
+                       
+               } else {
+                       graph.claim(target, relation, newDocument);
+                       FileDocumentUtil.createUniqueName(graph, newDocument);
+               }
+       }
+
+}
index e539df2c3aa27cdc0cb276363809d52e125e48ba..16a81f6f33636a772874d20b679637d3cfff7c67 100644 (file)
@@ -28,7 +28,6 @@ import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.common.request.ResourceRead;
 import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.common.request.WriteResultRequest;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
@@ -194,22 +193,15 @@ public class DocumentUtils {
                }
        }       
 
-       public void print(RequestProcessor processor, Resource res, String wiki, String css, DocumentSettings settings, final PdfWriter writer, final Document document) throws DocumentException {
-               try {
-                       Exportable exp = processor.syncRequest(new UniqueRead<Exportable>() {
-
-                               @Override
-                               public Exportable perform(ReadGraph graph) throws DatabaseException {
-                                       return new Exportable(graph, res, wiki, css, settings, true);
-                               }
-                               
-                       });
-                       exp.export(document, writer);
-               } catch (DocumentException e) {
-                       Logger.defaultLogError(e);
-               } catch (DatabaseException e) {
-                       Logger.defaultLogError(e);
-               }
+       public int print(RequestProcessor processor, Resource res, String wiki, String css, DocumentSettings settings, final PdfWriter writer, final Document document)
+                       throws DocumentException, DatabaseException {
+               Exportable exp = processor.syncRequest(new UniqueRead<Exportable>() {
+                       @Override
+                       public Exportable perform(ReadGraph graph) throws DatabaseException {
+                               return new Exportable(graph, res, wiki, css, settings, true);
+                       }
+               });
+               return exp.export(document, writer);
        }
 
     public static String indexRootPath(ReadGraph graph, Variable selection) throws DatabaseException {
diff --git a/bundles/org.simantics.document/src/org/simantics/document/DocumentVersionUtils.java b/bundles/org.simantics.document/src/org/simantics/document/DocumentVersionUtils.java
new file mode 100644 (file)
index 0000000..819a06a
--- /dev/null
@@ -0,0 +1,178 @@
+package org.simantics.document;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.DocumentResource;
+import org.simantics.layer0.Layer0;
+/**
+ * Util class for managing document versions
+ * 
+ * Document version history mode  is searched with relations:
+ * 1. l0.PartOf
+ * 2. l0.IsOwnedBy
+ * 3. l0.IsDependencyOf 
+ * 
+ * If library is not found, history mode is assumed to be flat.
+ * 
+ * In order to have working tree history, the library must contain proper configuration for relations:
+ *  doc.HasLibraryRelation
+ *  doc.HasVersionType
+ *  
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public class DocumentVersionUtils {
+
+       public enum VersionMode{FLAT,TREE};
+       
+       
+       /**
+        * Adds a new document version.
+        * 
+        * Expects that newDocument is not part of document version chain, and oldDocument does not have newer version.
+        * 
+        * @param graph
+        * @param oldDocument
+        * @param newDocument
+        * @param relation
+        * @throws DatabaseException
+        */
+       public static void createNewVersion(WriteGraph graph, Resource oldDocument, Resource newDocument, Resource relation) throws DatabaseException{
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               if (graph.hasStatement(oldDocument, doc.HasNewerVersion))
+                       throw new DatabaseException("Document " + NameUtils.getSafeName(graph, oldDocument) +" has already new version");
+               
+               Resource inverse = graph.getInverse(relation);
+               Resource lib = graph.getSingleObject(oldDocument, inverse);
+               String modeString = graph.getPossibleRelatedValue(lib, doc.HasVersionType);
+               VersionMode mode = VersionMode.FLAT;
+               if (modeString != null)
+                       mode = VersionMode.valueOf(modeString);
+               
+               graph.claim(oldDocument, doc.HasNewerVersion, newDocument);
+               graph.claim(lib, relation, newDocument);
+               
+               if (mode == VersionMode.TREE) {
+                       graph.deny(lib,relation,oldDocument);
+                       graph.claim(newDocument,relation,oldDocument);
+               }
+               FileDocumentUtil.createUniqueName(graph, newDocument);
+       }
+       
+       /**
+        * Sets document version relationship between two documents. 
+        * 
+        * If the documents are already part of the same version chain this method does nothing.
+        * 
+        * If documents are already set to some version chain with given relation, this method replaces the exiting links.
+        * 
+        * @param graph
+        * @param document1
+        * @param document2
+        * @param versionRel
+        * @throws DatabaseException
+        */
+       public static void setVersion(WriteGraph graph, Resource document1, Resource document2, Resource versionRel) throws DatabaseException {
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               // document type must match
+               if (!graph.getSingleType(document2, doc.Document).equals(graph.getSingleType(document1, doc.Document)))
+                       return;
+               if (!versionRel.equals(doc.HasNewerVersion) && !(versionRel.equals(doc.HasOlderVersion)))
+                       throw new IllegalArgumentException("Unknow version relation + " + graph.getPossibleURI(versionRel));
+               
+               Resource versionRelInv = graph.getInverse(versionRel);
+               // toSet must not be part of the document's version history
+               Resource r = document1;
+               while (r != null) {
+                       if (r.equals(document2))
+                               return;
+                       r = graph.getPossibleObject(r, versionRel);
+               }
+               
+               r = document2;
+               while (r != null) {
+                       if (r.equals(document1))
+                               return;
+                       r = graph.getPossibleObject(r, versionRel);
+               }
+               // At the moment document revision history is linear (no branching).
+               Resource document1Ver = graph.getPossibleObject(document1, versionRel);
+               if (document1Ver != null)
+                       unsetVersion(graph, document1, document1Ver, versionRel);
+               Resource document2Ver = graph.getPossibleObject(document2, versionRelInv);
+               if (document2Ver != null)
+                       unsetVersion(graph, document2, document2Ver, versionRelInv);
+               
+               graph.claim(document1, versionRel, document2);
+               
+               Resource lib = getLib(graph, document1);
+               if (lib != null) {
+                       Resource relation = graph.getPossibleObject(lib, doc.HasLibraryRelation);
+                       String type= graph.getPossibleRelatedValue(lib, doc.HasVersionType);
+                       if ("TREE".equals(type) && relation != null) {
+                               if (versionRel.equals(doc.HasOlderVersion)) {
+                                       graph.deny(document2, graph.getInverse(relation));
+                                       graph.claim(document1,relation,document2);
+                               } else {
+                                       graph.deny(document1, graph.getInverse(relation));
+                                       graph.claim(document2,relation,document1);
+                               }
+                       }
+                       
+               }
+       }
+       
+       /**
+        * Unlinks document version relationship between two documents. 
+        * @param graph
+        * @param document1
+        * @param document2
+        * @param versionRel
+        * @throws DatabaseException
+        */
+       public static void unsetVersion(WriteGraph graph, Resource document1, Resource document2, Resource versionRel) throws DatabaseException {
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               if (!versionRel.equals(doc.HasNewerVersion) && !(versionRel.equals(doc.HasOlderVersion)))
+                       throw new IllegalArgumentException("Unknow version relation + " + graph.getPossibleURI(versionRel));
+               
+               graph.deny(document1, versionRel,document2);
+               Resource lib = getLib(graph, document1);
+               if (lib != null) {
+                       Resource relation = graph.getPossibleObject(lib, doc.HasLibraryRelation);
+                       String type= graph.getPossibleRelatedValue(lib, doc.HasVersionType);
+                       if ("TREE".equals(type) && relation != null) {
+                               if (versionRel.equals(doc.HasOlderVersion)) {
+                                       graph.deny(document1, relation);
+                                       graph.claim(lib,relation,document2);
+                                       FileDocumentUtil.createUniqueName(graph, document2);
+                               } else {
+                                       graph.deny(document1, graph.getInverse(relation));
+                                       graph.claim(lib,relation,document1);
+                                       FileDocumentUtil.createUniqueName(graph, document1);
+                               }
+                       }
+                       
+               }
+       }
+       
+       private static Resource getLib(ReadGraph graph, Resource document) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(graph);
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               Resource r = document;
+               while (true) {
+                       Resource lib = graph.getPossibleObject(r, l0.PartOf);
+                       if (lib == null)
+                               lib = graph.getPossibleObject(r, l0.IsOwnedBy);
+                       if (lib == null)
+                               lib =  graph.getPossibleObject(r, l0.IsDependencyOf);
+                       if (lib == null)
+                               return null;
+                       if (!graph.isInstanceOf(lib, doc.Document))
+                               return lib;
+                       r = lib;
+               }
+       }
+}
index a1053dd83001dafde9e6923f2a569b3b3d8f1585..a6dd790de51b78937f71ad627f1b27a2e1a01edd 100644 (file)
@@ -105,7 +105,7 @@ public class Exportable implements IExportable {
        }
 
        @Override
-       public void export(Document document, PdfWriter writer) throws DocumentException {
+       public int export(Document document, PdfWriter writer) throws DocumentException {
 
                File temp = Simantics.getTempfile("wikiPdfExport", "pdf");
                try {
@@ -113,6 +113,7 @@ public class Exportable implements IExportable {
                        temp.getParentFile().mkdirs();
                        PhantomJSDriver.print(html, settings, temp);
                        
+                       int result = 0;
                PdfContentByte cb = writer.getDirectContent();
                PdfReader reader = new PdfReader(new BufferedInputStream(new FileInputStream(temp)));
                for (int i = 1; i <= reader.getNumberOfPages(); i++) {
@@ -123,8 +124,10 @@ public class Exportable implements IExportable {
                        //add the page to the destination pdf
                        float pts = Utilities.millimetersToPoints(10);
                        cb.addTemplate(page, pts, pts);
+                       ++result;
                }
 
+               return result;
                } catch (IOException e) {
 
                        throw new DocumentException(e);
diff --git a/bundles/org.simantics.document/src/org/simantics/document/FileDocumentUtil.java b/bundles/org.simantics.document/src/org/simantics/document/FileDocumentUtil.java
new file mode 100644 (file)
index 0000000..cab7e9a
--- /dev/null
@@ -0,0 +1,474 @@
+package org.simantics.document;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.graphfile.ontology.GraphFileResource;
+import org.simantics.graphfile.util.GraphFileUtil;
+import org.simantics.layer0.Layer0;
+import org.simantics.utils.ui.ExceptionUtils;
+
+/**
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public class FileDocumentUtil {
+       
+       /**
+        * Imports file, sets its L0.hasName, and and adds it to a library
+        * 
+        * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
+        * 
+        * @param fileName
+        * @param lib
+        * @param rel
+        * @throws DatabaseException 
+        */
+       public static Resource importFile(final String fileName, final Resource lib, final Resource rel) throws DatabaseException {
+               return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
+                       @Override
+                       public Resource perform(WriteGraph graph) throws DatabaseException {
+                               return importFile(graph, fileName,lib,rel);
+                       }
+               });
+                       
+               
+       }
+       
+       public static void importFileAsync(final String fileName, final Resource lib, final Resource rel)  {
+               Simantics.getSession().asyncRequest(new WriteRequest() {
+                       
+                       @Override
+                       public void perform(WriteGraph graph) throws DatabaseException {
+                                importFile(graph, fileName,lib,rel);
+                               
+                       }
+               },new org.simantics.utils.datastructures.Callback<DatabaseException>() {
+                       
+                       @Override
+                       public void run(DatabaseException parameter) {
+                               if (parameter != null)
+                                       ExceptionUtils.logAndShowError("Cannot import file " + fileName, parameter);
+                               
+                       }
+               });
+                       
+               
+       }
+       
+       /**
+        * Imports file, sets its L0.HasName, and and adds it to a library
+        * 
+        * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
+        * 
+        * @param graph
+        * @param fileName
+        * @param lib
+        * @param rel
+        * @throws DatabaseException
+        */
+       public static Resource importFile(WriteGraph graph, String fileName, Resource lib, Resource rel) throws DatabaseException{
+               Layer0 l0 = Layer0.getInstance(graph);
+               Resource fileResource = importFile(graph, fileName);
+               graph.claim(lib, rel, fileResource);
+               File file = new File(fileName);
+               String name = file.getName();
+               graph.claimLiteral(fileResource, l0.HasName, name);
+               setUniqueName(graph, fileResource, lib, rel);
+               return fileResource;
+       }
+       
+       public static Resource importFileWithName(WriteGraph graph, String fileName) throws DatabaseException{
+               Layer0 l0 = Layer0.getInstance(graph);
+               Resource fileResource = importFile(graph, fileName);
+               File file = new File(fileName);
+               String name = file.getName();
+               graph.claimLiteral(fileResource, l0.HasName, name);
+               return fileResource;
+       }
+       
+       /**
+        * Imports folder of documents recursively (including all sub folders). 
+        * @param graph
+        * @param folderName  Name of imported folder
+        * @param lib         Library, where imported folder is attached.
+        * @param folderType  Type of folders
+        * @param relation    Relation used to create file/folder hierarchy
+        * @return            the imported folder
+        * @throws DatabaseException
+        */
+       public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource lib, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
+               Resource folderRes = importFolderWithName(graph, folderName, folderType, relation,monitor);
+               graph.claim(lib, relation, folderRes);
+               FileDocumentUtil.createUniqueName(graph, folderRes);
+               return folderRes;
+       }
+       
+       /**
+        * Imports folder of documents recursively (including all sub folders). 
+        * @param graph
+        * @param folderName  Name of imported folder
+        * @param folderType  Type of folders
+        * @param relation    Relation used to create file/folder hierarchy
+        * @param monitor     ProgessMonitor or null
+        * @return            the imported folder
+        * @throws DatabaseException
+        */
+       public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
+               Layer0 l0 = Layer0.getInstance(graph);
+               File folder = new File(folderName);
+               Resource rootFolderRes = graph.newResource();
+               graph.claim(rootFolderRes, l0.InstanceOf, folderType);
+               graph.claimLiteral(rootFolderRes, l0.HasName, folder.getName());
+               importFolder(graph, folder, rootFolderRes, relation, monitor);
+               return rootFolderRes;
+       }
+       
+       /**
+        * Imports folder of documents recursively (including all sub folders).
+        * @param graph
+        * @param folder            Imported folder
+        * @param folderResource    Resource folder matching file system folder
+        * @param relation          Relation used to create file/folder hierarchy
+        * @throws DatabaseException
+        */
+       public static void importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
+               if (monitor != null) {
+                       int count = _countFiles(folder);
+                       monitor.beginTask("Import files", count);
+               }
+               _importFolder(graph, folder, folderResource, relation, monitor);
+               if (monitor != null)
+                       monitor.done();
+       }
+       
+       private static void _importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
+               Layer0 l0 = Layer0.getInstance(graph);
+               File files[] = folder.listFiles();
+               for (File f : files) {
+                       if (f.isDirectory()) {
+                               Resource newFolderRes = graph.newResource();
+                               graph.claim(newFolderRes, l0.InstanceOf, graph.getSingleType(folderResource));
+                               graph.claim(folderResource, relation, newFolderRes);
+                               graph.claimLiteral(newFolderRes, l0.HasName, f.getName());
+                               _importFolder(graph, f, newFolderRes, relation,monitor);
+                       } else {
+                               Resource fileRes = null;
+                               if (isUrl(f)) {
+                               } else {
+                                   fileRes = importURL(graph, f);
+                                       fileRes = importFileWithName(graph, f.getAbsolutePath());
+                               }
+                               graph.claim(folderResource, relation, fileRes);
+                               if (monitor != null)
+                                       monitor.worked(1);
+                       }
+               }
+       }
+       
+       private static int _countFiles(File folder) {
+               
+               int count = 0;
+               File files[] = folder.listFiles();
+               for (File f : files) {
+                       if (f.isDirectory()) {
+                               count += _countFiles(f);
+                       } else {
+                               count++;
+                       }
+               }
+               return count;
+       }
+       
+       
+       public static void createUniqueName(WriteGraph graph, Resource document) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(graph);
+               Resource lib = graph.getPossibleObject(document, l0.PartOf);
+               if (lib == null)
+                       return;
+               setUniqueName(graph, document, lib, l0.ConsistsOf);
+       }
+       
+       public static void setUniqueName(WriteGraph graph, Resource res, Resource lib, Resource rel) throws DatabaseException{
+               Layer0 l0 = Layer0.getInstance(graph);
+               Set<String> names = new HashSet<String>();
+               for (Resource r : graph.getObjects(lib, rel)) {
+                       if (r.equals(res))
+                               continue;
+                       names.add((String)graph.getRelatedValue(r, l0.HasName));
+               }
+               String name = graph.getRelatedValue(res, l0.HasName);
+               if (!names.contains(name))
+                       return;
+               int i = 1;
+               while (true) {
+                       String proposal = name +" (" + i +")";
+                       if (!names.contains(proposal)) {
+                               graph.claimLiteral(res, l0.HasName, proposal);
+                               return;
+                       }
+                       i++;
+               }
+               
+       }
+       
+       /**
+        * Imports a file
+        * 
+        * @param graph
+        * @param fileName
+        * @return
+        * @throws DatabaseException
+        */
+       public static Resource importFile(WriteGraph graph, String fileName) throws DatabaseException{
+               Layer0 l0 = Layer0.getInstance(graph);
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               
+               Resource fileResource = graph.newResource();
+               graph.claim(fileResource, l0.InstanceOf, doc.FileDocument);
+               try {
+                       GraphFileUtil.toGraph(graph,fileName, fileResource);
+                       
+               } catch (IOException e) {
+                       throw new DatabaseException(e);
+               }
+               return fileResource;
+               
+       }
+       
+       /**
+        * Exports graph folder recursively to file system. 
+        * @param graph
+        * @param folderResource
+        * @param folder
+        * @param relation
+        * @throws DatabaseException
+        */
+       public static void exportDocumentFolder(final Resource folderResource, final File folder, final Resource relation, boolean useResourceNames, final IProgressMonitor monitor) throws Exception{
+               Simantics.getSession().syncRequest(new ReadRequest() {
+                       
+                       @Override
+                       public void run(ReadGraph graph) throws DatabaseException {
+                               try {
+                                       exportDocumentFolder(graph, folderResource, folder, relation, useResourceNames, monitor);
+                               } catch (Exception e) {
+                                       throw new DatabaseException(e);
+                               }
+                               
+                       }
+               });
+       }
+       
+       
+       /**
+        * Exports graph folder recursively to file system. 
+        * @param graph
+        * @param folderResource
+        * @param folder
+        * @param relation
+        * @throws DatabaseException
+        */
+       public static void exportDocumentFolder(ReadGraph graph, Resource folderResource, File folder, Resource relation, boolean useResourceNames, IProgressMonitor monitor) throws Exception{
+               Layer0 l0 = Layer0.getInstance(graph);
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               GraphFileResource gf = GraphFileResource.getInstance(graph);
+               Set<String> names = new HashSet<String>();
+               Collection<Resource> folderType = graph.getPrincipalTypes(folderResource);
+               for (Resource r : graph.getObjects(folderResource, relation)) {
+                       if (graph.isInstanceOf(r, doc.Document)) {
+                               String name = null;
+                               boolean canExport = false;
+                               if (graph.isInstanceOf(r, doc.FileDocument)) {
+                                       name = graph.getRelatedValue(r, useResourceNames ? gf.HasResourceName : l0.HasName);
+                                       canExport = true;
+                               } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
+                                       name = graph.getRelatedValue(r, l0.HasName) +".url";
+                                       canExport = true;
+                               }
+                               if (canExport) {
+                                       name = resolveName(folder, name, names, true);
+                                       File file = new File(folder.getAbsolutePath()+"/"+name);
+                                       if (graph.isInstanceOf(r, doc.FileDocument)) {
+                                               GraphFileUtil.writeDataToFile(graph,r, file);
+                                       } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
+                                               String url = graph.getRelatedValue(r, doc.HasUrl);
+                                               String n = graph.getRelatedValue(r, l0.HasName);
+                                               exportUrl(file, n, url);
+                                       }
+                                       if (monitor != null)
+                                               monitor.worked(1);
+                               }
+                               
+                       } else {
+                               Collection<Resource> type = graph.getPrincipalTypes(r);
+                               if (type.size() == folderType.size() && folderType.containsAll(type)) {
+                                       String name = graph.getRelatedValue(r, l0.HasName);
+                                       name = resolveName(folder, name, names, false);
+                                       File subFolder = new File(folder.getAbsolutePath()+"/"+name);
+                                       if (!subFolder.exists()) {
+                                               if (!subFolder.mkdir()) {
+                                                       // TODO : error.
+                                                       continue;
+                                               }
+                                       }
+                                       exportDocumentFolder(graph, r, subFolder, relation, useResourceNames, monitor);
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Print URL to a file (Windows specific format?)
+        * @param toFile
+        * @param url
+        * @throws DatabaseException
+        */
+       private static void exportUrl(File toFile, String name, String url) throws Exception{
+               PrintStream os = new PrintStream(toFile,"UTF-8");
+               os.println("[InternetShortcut]");
+               os.println("URL="+url);
+               os.println("name="+name);
+               os.flush();
+               os.close();
+       }
+       
+       public static Resource importURL(WriteGraph graph, File file) throws Exception{
+               String s = null;
+               String url = null;
+               String name = null;
+               BufferedReader is = null;
+               try {
+               is = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
+               while ((s = is.readLine()) != null) {
+                       if (s.startsWith("URL=")) {
+                               url = s.substring(4);
+                       } else if (s.startsWith("name=")) {
+                               name = s.substring(5);
+                       }
+               }
+               } finally {
+                   if (is != null)
+                       is.close();
+               }
+               
+               if (url == null)
+                       return null;
+               
+               Layer0 l0 = Layer0.getInstance(graph);
+               DocumentResource doc = DocumentResource.getInstance(graph);
+               
+               Resource fileResource = graph.newResource();
+               graph.claim(fileResource, l0.InstanceOf, doc.UrlDocument);
+               if (name == null) {
+                       name = file.getName();
+                       name = unescape(name);
+                       name = name.substring(0,name.length()-4);
+               }
+               graph.claimLiteral(fileResource, l0.HasName, name);
+               graph.claimLiteral(fileResource, doc.HasUrl, url);
+               return fileResource;
+       }
+       
+       private static boolean isUrl(File file) throws Exception{
+               return (file.getAbsolutePath().endsWith(".url"));
+       }
+       
+       private static final char ESCAPE = '%';
+       
+       private static String escape(String s) {
+               
+               int len = s.length();
+               StringBuilder sb = new StringBuilder(len);
+               for (int i = 0; i < len; i++) {
+                   char ch = s.charAt(i);
+                   if (ch < ' ' || ch >= 0x7F || ch == '/'  || ch == '\\' || ch == ':' || ch == ESCAPE) {
+                       sb.append(ESCAPE);
+                       if (ch < 0x10) {
+                           sb.append('0');
+                       }
+                       sb.append(Integer.toHexString(ch));
+                   } else {
+                       sb.append(ch);
+                   }
+               }
+               return sb.toString();
+       }
+       
+       private static String unescape(String s) {
+               int len = s.length();
+               StringBuilder sb = new StringBuilder(len);
+               for (int i = 0; i < len; i++) {
+                   char ch = s.charAt(i);
+                   if (ch == ESCAPE) {
+                       String num = "0x";
+                       num += s.charAt(++i);
+                       num += s.charAt(++i);
+                       ch = (char)Integer.decode(num).intValue();
+                   }
+                   sb.append(ch);
+               }
+               return sb.toString();
+               
+       }
+       
+       private static String resolveName(File parentFolder, String proposal, Set<String> used, boolean file) {
+               String current = escape(proposal);
+               int i = 0;
+               if (file) {
+                       while (true) {
+                               i++;
+                               if (used.contains(current)) {
+                                       current = createFileName(proposal, i);
+                               } else {
+                                       File subFile = new File(parentFolder.getAbsolutePath()+"/"+current);
+                                       if (!subFile.exists())
+                                               break;
+                                       if (subFile.exists() && subFile.isFile() && subFile.canWrite()) {
+                                               break;
+                                       }
+                               }
+                       }
+               } else {
+                       while (true) {
+                               i++;
+                               if (used.contains(current)) {
+                                       current = proposal+i;
+                               } else {
+                                       File subFolder = new File(parentFolder.getAbsolutePath()+"/"+current);
+                                       if (!subFolder.exists())
+                                               break;
+                                       if (subFolder.exists() && subFolder.isDirectory()) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               used.add(current);
+               return current;
+       }
+       
+       private static String createFileName(String original, int i) {
+               int extIndex = original.lastIndexOf(".");
+               if (extIndex == -1)
+                       return original+i;
+               return original.substring(0,extIndex) + i + original.substring(extIndex);
+       }
+
+}
diff --git a/bundles/org.simantics.document/src/org/simantics/document/ImportDocument.java b/bundles/org.simantics.document/src/org/simantics/document/ImportDocument.java
new file mode 100644 (file)
index 0000000..c8d3ee3
--- /dev/null
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.document;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.simantics.DatabaseJob;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+
+/**
+ * Action for importing files as documents.
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public class ImportDocument extends AddDocumentAction {
+       
+
+       public ImportDocument(ReadGraph graph, String relationUri) throws DatabaseException {
+               super(graph, relationUri);
+       }
+
+       @Override
+       public Runnable create(Object target) {
+               if(!(target instanceof Resource))
+                       return null;
+               final Resource resource = (Resource)target;
+               return new Runnable() {
+                       
+                       @Override
+                       public void run() {
+                               FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell(),SWT.OPEN | SWT.MULTI);
+                               // TODO : is there any way to read file/executable bindings from OS?
+                               //        if is, use those extensions to filter this list.
+                               //        note: in windows using "reg query ..." to read bindings form registry would work.
+                               // Note : If the above mentioned filtering is implemented it should be made optional / configurable.
+                               dialog.setFilterExtensions(new String[]{"*.*"});
+                               if (dialog.open() == null) return;
+
+                               String filterPath = dialog.getFilterPath();
+                               String[] filenames = dialog.getFileNames();
+                               
+                               ImportJob job = new ImportJob(filenames.length > 1 ? "Import files" : "Import file", resource, filterPath, filenames);
+                               job.setUser(true);
+                               job.schedule();
+                       }
+               };
+       }
+       
+       private class ImportJob extends DatabaseJob {
+
+               public ImportJob(String name, Resource resource, String path, String[] filenames) {
+                       super(name);
+                       this.resource = resource;
+                       this.path = path;
+                       this.filenames = filenames;
+               }
+
+               Resource resource;
+               String path;
+               String[] filenames;
+
+               @Override
+               protected IStatus run(final IProgressMonitor monitor) {
+                       monitor.beginTask("Importing...", filenames.length);
+                       try {
+                               Simantics.getSession().syncRequest(new WriteRequest() {
+                                       @Override
+                                       public void perform(WriteGraph graph) throws DatabaseException {
+                                               try {
+                                                       graph.markUndoPoint();
+                                                   for (String filename : filenames) {
+                                                       File f = new File(path, filename);
+                                                       Resource newDoc = FileDocumentUtil.importFileWithName(graph, f.getAbsolutePath());
+                                                       linkDocument(graph, resource, newDoc);
+                                                           monitor.worked(1);
+                                                   }
+                                               } catch (Exception e) {
+                                                       throw new DatabaseException(e);
+                                               }
+                                       }
+                               });
+                               return new Status(IStatus.OK, Activator.PLUGIN_ID, "Import succesful.");
+                       } catch (DatabaseException e) {
+                               return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import failed.", e);
+                       } finally {
+                               monitor.done();
+                       }
+               }
+       }
+       
+}
index 9711fbccf06e02ca60b01f837ed7e0f0b757a2d7..9e80cd16f1e828ac26955c7efb15ba61799b8ede 100644 (file)
@@ -46,7 +46,6 @@ import com.lowagie.text.Document;
 import com.lowagie.text.DocumentException;
 import com.lowagie.text.FontFactory;
 import com.lowagie.text.Rectangle;
-import com.lowagie.text.pdf.DefaultFontMapper;
 import com.lowagie.text.pdf.PdfBoolean;
 import com.lowagie.text.pdf.PdfCopy;
 import com.lowagie.text.pdf.PdfName;
@@ -160,7 +159,7 @@ public class ExportPdfFormat implements FormatClass {
                        writer.fos = new FileOutputStream(writer.outputFile);
                        writer.pdfCopy = new PdfCopy(writer.document, writer.fos); 
                        writer.pdfCopy.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
-                       writer.fontMapper = new DefaultFontMapper();
+                       writer.fontMapper = FontMapping.defaultFontMapper();
                        writer.options = options;
                        writer.ctx = ctx;
 
index 204763b687175b215e1a31531d236e54629e1bb3..97488908ee1822c04ec9a9a183483626baa0486f 100644 (file)
@@ -317,10 +317,10 @@ public class ExportPdfWriter {
                                try {
                                int n = reader.getNumberOfPages();
 
-                               for (int i = 0; i < n; ) {
-                                   Rectangle pageSize = reader.getPageSizeWithRotation(n);
+                               for (int i = 1; i <= n; ++i) {
+                                   Rectangle pageSize = reader.getPageSizeWithRotation(i);
 
-                                   PdfImportedPage imp = pdfCopy.getImportedPage(reader, ++i);
+                                   PdfImportedPage imp = pdfCopy.getImportedPage(reader, i);
                                    PdfCopy.PageStamp ps = pdfCopy.createPageStamp(imp);
 
                                    PdfContentByte over = ps.getOverContent();
diff --git a/bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/FontMapping.java b/bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/FontMapping.java
new file mode 100644 (file)
index 0000000..9c68b16
--- /dev/null
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.export.core.pdf;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.lowagie.text.FontFactory;
+import com.lowagie.text.pdf.DefaultFontMapper;
+import com.lowagie.text.pdf.FontMapper;
+
+/**
+ * A utility class for constructing properly initialize iText {@link FontMapper}
+ * instances.
+ * 
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class FontMapping {
+
+       private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();
+
+       public static FontMapper defaultFontMapper() {
+               // NOTE: recreation is intentional because users might add fonts between exports.
+               // At some point, perhaps we could listen to file system changes in these locations
+               // and only then recreate the mapper.
+               return createDefaultFontMapper(); 
+       }
+
+       public static FontMapper createDefaultFontMapper() {
+               initializeFontFactory();
+               DefaultFontMapper mapper = new DefaultFontMapper();
+               insertDirectories(mapper);
+               return mapper;
+       }
+
+       private static void insertDirectories(DefaultFontMapper mapper) {
+               switch (OSType.calculate()) {
+               case APPLE:
+                       mapper.insertDirectory("/Library/Fonts");
+                       mapper.insertDirectory("/System/Library/Fonts");
+
+               case LINUX:
+               case SUN:
+                       mapper.insertDirectory("/usr/share/X11/fonts");
+                       mapper.insertDirectory("/usr/X/lib/X11/fonts");
+                       mapper.insertDirectory("/usr/openwin/lib/X11/fonts");
+                       mapper.insertDirectory("/usr/share/fonts");
+                       mapper.insertDirectory("/usr/X11R6/lib/X11/fonts");
+                       break;
+
+               case WINDOWS:
+                       String windir = System.getenv("WINDIR");
+                       if (windir != null && !windir.isEmpty()) {
+                               mapper.insertDirectory(windir + "\\Fonts");
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       private static void initializeFontFactory() {
+               if (!fontFactoryInitialized.compareAndSet(false, true))
+                       return;
+
+               switch (OSType.calculate()) {
+               case APPLE:
+                       FontFactory.registerDirectory("/Library/Fonts");
+                       FontFactory.registerDirectory("/System/Library/Fonts");
+
+               case LINUX:
+               case SUN:
+                       FontFactory.registerDirectory("/usr/share/X11/fonts", true);
+                       FontFactory.registerDirectory("/usr/X/lib/X11/fonts", true);
+                       FontFactory.registerDirectory("/usr/openwin/lib/X11/fonts", true);
+                       FontFactory.registerDirectory("/usr/share/fonts", true);
+                       FontFactory.registerDirectory("/usr/X11R6/lib/X11/fonts", true);
+                       break;
+
+               case WINDOWS:
+                       String windir = System.getenv("WINDIR");
+                       if (windir != null && !windir.isEmpty()) {
+                               FontFactory.registerDirectory(windir + "\\Fonts");
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       static enum OSType {
+               APPLE, LINUX, SUN, WINDOWS, UNKNOWN;
+
+               public static OSType calculate() {
+                       String osName = System.getProperty("os.name");
+                       assert osName != null;
+                       osName = osName.toLowerCase();
+                       if (osName.startsWith("mac os x"))
+                               return APPLE;
+                       if (osName.startsWith("windows"))
+                               return WINDOWS;
+                       if (osName.startsWith("linux"))
+                               return LINUX;
+                       if (osName.startsWith("sun"))
+                               return SUN;
+                       return UNKNOWN;
+               }
+       }
+
+}
diff --git a/bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/PageNumbering.java b/bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/PageNumbering.java
new file mode 100644 (file)
index 0000000..edf4e72
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.export.core.pdf;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.BadPdfFormatException;
+import com.lowagie.text.pdf.ColumnText;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfCopy;
+import com.lowagie.text.pdf.PdfImportedPage;
+import com.lowagie.text.pdf.PdfReader;
+import com.lowagie.text.pdf.PdfWriter;
+
+/**
+ * PDF page numbering related post-processing utilities using iText.
+ * 
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class PageNumbering {
+
+       public static enum NumberingFormat {
+               PAGE_SLASH_TOTAL_PAGES
+       }
+
+       public static enum Position {
+               BOTTOM_LEFT,
+               BOTTOM_RIGHT,
+               TOP_LEFT,
+               TOP_RIGHT,
+       }
+
+       private static int pageNumberAlignment(Position positioning) {
+               switch (positioning) {
+               case BOTTOM_LEFT:
+               case TOP_LEFT:  return Element.ALIGN_LEFT;
+
+               case BOTTOM_RIGHT:
+               case TOP_RIGHT:
+               default: return Element.ALIGN_RIGHT;
+               }
+       }
+
+       private static Point2D.Float pageNumberPosition(Position positioning, Rectangle pageSize, Font font) {
+               switch (positioning) {
+               case TOP_LEFT:
+                       return new Point2D.Float(12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
+               case TOP_RIGHT:
+                       return new Point2D.Float(pageSize.getWidth() - 12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
+               case BOTTOM_LEFT:
+                       return new Point2D.Float(12, 12);
+               case BOTTOM_RIGHT: 
+               default:
+                       return new Point2D.Float(pageSize.getWidth() - 12, 12);
+               }
+       }
+
+       public static String formatPageNumber(NumberingFormat format, int pageNumber, int totalPages) {
+               switch (format) {
+               case PAGE_SLASH_TOTAL_PAGES: return String.format("%d / %d", pageNumber, totalPages);
+               default:
+                       throw new UnsupportedOperationException("Unsupported numbering format: " + format);
+               }
+       }
+
+       public static void addPageNumber(
+                       PdfCopy pdfCopy,
+                       PdfReader sourceReader,
+                       int sourcePageNumber,
+                       int currentPageNumber,
+                       int totalPages,
+                       Font font,
+                       Position positioning,
+                       NumberingFormat format)
+                                       throws IOException, BadPdfFormatException
+       {
+               Rectangle pageSize = sourceReader.getPageSizeWithRotation(sourcePageNumber);
+               PdfImportedPage imp = pdfCopy.getImportedPage(sourceReader, sourcePageNumber);
+               PdfCopy.PageStamp ps = pdfCopy.createPageStamp(imp);
+               PdfContentByte over = ps.getOverContent();
+               String text = formatPageNumber(format, currentPageNumber, totalPages);
+               Point2D.Float pos = pageNumberPosition(positioning, pageSize, font);
+               int alignment = pageNumberAlignment(positioning);
+               ColumnText.showTextAligned(over, alignment, new Phrase(text, font), pos.x, pos.y, 0);
+               ps.alterContents();
+               pdfCopy.addPage(imp);
+       }
+
+       public static void addPageNumbers(
+                       IProgressMonitor monitor,
+                       Path inputFile,
+                       Path outputFile,
+                       Position positioning,
+                       NumberingFormat format,
+                       Font pageNumberFont)
+                                       throws IOException, DocumentException
+       {
+               PdfReader reader = null;
+               try {
+                       reader = new PdfReader(inputFile.toString());
+                       int totalPages = reader.getNumberOfPages();
+                       int currentPage = 1;
+
+                       SubMonitor mon = SubMonitor.convert(monitor, totalPages);
+
+                       try (OutputStream fos = Files.newOutputStream(outputFile)) {
+                               Document document = new Document();
+                               PdfCopy pdfCopy = new PdfCopy(document, fos); 
+                               pdfCopy.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
+                               document.open();
+                               try {
+                                       for (int i = 1; i <= totalPages; ++i) {
+                                               mon.subTask(i + "/" + totalPages);
+                                               PageNumbering.addPageNumber(pdfCopy, reader, i,
+                                                               currentPage++, totalPages,
+                                                               pageNumberFont,
+                                                               positioning,
+                                                               format);
+                                       }
+                               } finally {
+                                       if (document != null && document.isOpen())
+                                               document.close();
+                                       if (pdfCopy != null)
+                                               pdfCopy.close();
+                               }
+                       }
+               } finally {
+                       if (reader != null)
+                               reader.close();
+               }
+
+       }
+
+       public static void addPageNumbers(
+                       IProgressMonitor monitor,
+                       Path inputFile,
+                       Path outputFile,
+                       Position positioning,
+                       NumberingFormat format)
+                                       throws IOException, DocumentException
+       {
+               addPageNumbers(monitor, inputFile, outputFile, positioning, format, new Font(Font.HELVETICA, 8));
+       }
+
+}
\ No newline at end of file
index 94cc4b9d270782b7654d5c19fe365f2602fb87e1..db1100bc370c780c823d029993b6c597e4c36540 100644 (file)
@@ -9,7 +9,8 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100.v20150407-1430",
  org.eclipse.e4.core.di,
  org.eclipse.e4.ui.services,
- org.simantics.fileimport;bundle-version="1.0.0"
+ org.simantics.fileimport;bundle-version="1.0.0",
+ org.slf4j.api
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.inject;version="1.0.0"
 Bundle-ActivationPolicy: lazy
index 3da6858a3f35ef51021632aab00ecfb95d07cb2d..21f8d3c4d8b6dc52767e3b1b9b5b8357df192191 100644 (file)
@@ -4,6 +4,7 @@ package org.simantics.fileimport.ui;
 import java.nio.file.Paths;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.Consumer;
 
 import javax.inject.Named;
 
@@ -14,9 +15,13 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Shell;
 import org.simantics.fileimport.FileImportService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ImportFileHandler {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(ImportFileHandler.class);
+    
     @CanExecute
     public boolean canExecute() {
         return !FileImportService.supportedExtensionsWithFilters().isEmpty();
@@ -44,6 +49,9 @@ public class ImportFileHandler {
         final String fileName = dialog.open();
         if (fileName == null)
             return;
-        FileImportService.performFileImport(Paths.get(fileName), Optional.empty());
+
+        FileImportService.performFileImport(Paths.get(fileName), Optional.of((Consumer<Throwable>) t -> {
+            LOGGER.error("Could not import file " + fileName, t);
+        }));
     }
 }
\ No newline at end of file
index bbb632778cee2fbd035dbab3e06afaf990d0d12a..a8d8f0752c54d45171227163e5d40f34f0ffc570 100644 (file)
@@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.core.runtime,
  org.simantics,
  org.simantics.graphfile;bundle-version="0.1.0",
  org.simantics.graphfile.ontology;bundle-version="0.1.0",
- org.simantics.modeling;bundle-version="1.1.1"
+ org.simantics.modeling;bundle-version="1.1.1",
+ org.slf4j.api
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ActivationPolicy: lazy
 Export-Package: org.simantics.fileimport
index 7b3c354a35ddd40e73c9302a9a1af7c900b4559e..878326ba1e4ee6c7b42e99cc7f469f17071629f5 100644 (file)
@@ -7,6 +7,10 @@ importJava "org.simantics.fileimport.scl.DropinsSCL" where
     getUploadedFiles :: () -> <Proc> MMap.T String Long
     removeFileForId :: Long -> <Proc> ()
 
+
+importJava "org.simantics.fileimport.FileImportService" where
+    performFileImport :: String -> String -> <Proc> String
+
 getUploadedDropinFiles :: () -> <Proc> [Long]
 getUploadedDropinFiles dummy = do
     files = getUploadedFiles ()
index 9c0f77072c2cdbecb0071f3ac8f9022e36837902..2918674518aade7bed60e1780686ab5c8d18efea 100644 (file)
@@ -13,8 +13,9 @@ import org.simantics.fileimport.dropins.FileImportDropins;
 
 public class Activator implements BundleActivator {
 
-       private static BundleContext context;
+    private static BundleContext context;
        
+    private static Path modelsFolder = null;
        private static Path dropinsFolder = null;
 
        static BundleContext getContext() {
@@ -48,4 +49,14 @@ public class Activator implements BundleActivator {
            return dropinsFolder;
        }
 
+    public static Path getModelsFolder() throws IOException {
+        if (modelsFolder == null) {
+            IPath state = Platform.getStateLocation(context.getBundle());
+            modelsFolder = Paths.get(state.append("models").toOSString());
+            if (!Files.exists(modelsFolder))
+                Files.createDirectories(modelsFolder);
+        }
+        return modelsFolder;
+    }
+
 }
index fcbd3cc30c33a04f87993e8307a1fda32b895fc4..ddb9dabae71478a184ef9845af5debd7097327a8 100644 (file)
@@ -17,7 +17,11 @@ import java.util.function.Consumer;
 
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.simantics.databoard.util.Base64;
 import org.simantics.fileimport.dropins.FileImportDropins;
+import org.simantics.utils.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Utility class for Simantics File import functions
@@ -27,6 +31,8 @@ import org.simantics.fileimport.dropins.FileImportDropins;
  */
 public class FileImportService {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(FileImportService.class);
+    
     private FileImportService() {}
     
     public static final String DB_FILE = ".simanticsdb";
@@ -37,7 +43,7 @@ public class FileImportService {
             serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(),
                     null);
         } catch (InvalidSyntaxException e) {
-            e.printStackTrace();
+            LOGGER.error("Could not get service references for IGenericFileImport!", e);
         }
         if (serviceReferences.length == 0)
             return Collections.emptyList();
@@ -63,6 +69,33 @@ public class FileImportService {
 
         return extensionsWithFilters;
     }
+    
+    private static class ConsumerHolder implements Consumer<Throwable> {
+
+        private Throwable throwable;
+        
+        @Override
+        public void accept(Throwable t) {
+            throwable = t;
+        }
+        
+        public Throwable getThrowable() {
+            return throwable;
+        }
+        
+    }
+    
+    public static String performFileImport(String base64, String name) throws Throwable {
+        byte[] bytes = Base64.decode(base64);
+        Path file = Activator.getModelsFolder().resolve(name);
+        Files.write(file, bytes);
+        
+        ConsumerHolder holder = new ConsumerHolder();
+        String result = performFileImport(file, Optional.of(holder));
+        if (holder.getThrowable() != null)
+            throw holder.getThrowable();
+        return result;
+    }
 
     /**
      * Method that performs the import of the given file. This method is called when e.g. {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_CREATE} operation
@@ -70,22 +103,31 @@ public class FileImportService {
      * @param file Path file to be imported
      * @param callback Optional callback which can be used to catch Throwables thrown in the import process
      */
-    public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback) {
-        if (file.getFileName().toString().equals(DB_FILE))
-            return;
+    public static String performFileImport(Path file, Optional<Consumer<Throwable>> callback) {
+        if (file.getFileName().toString().equals(DB_FILE)) {
+            return null;
+        }
+        String result = "Import failed";
         Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
-        serviceOp.ifPresent(service -> {
+        if (serviceOp.isPresent()) {
+            IGenericFileImport service = serviceOp.get();
             try {
                 Optional<String> resource = service.perform(file);
                 saveResourceForPath(file, resource);
+                result = resource.get();
             } catch (Throwable t) {
                 if (callback.isPresent()) {
                     callback.get().accept(t);
                 } else {
-                    t.printStackTrace();
+                    LOGGER.error("Could not import file " + file, t);
                 }
             }
-        });
+        } else {
+            LOGGER.warn("Could not find service for importing file " + file);
+            if (callback.isPresent())
+                callback.get().accept(new Exception("Could not find IGenericFileImport service for file " + file));
+        }
+        return result;
     }
 
     
index 2fea9fde3dd2baac7146293af64b0c640862d513..aa367178125860447af3614a4a01086e3da77ea0 100644 (file)
@@ -6,21 +6,15 @@ import java.util.Map;
 import java.util.Optional;
 
 import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
 import org.simantics.graphfile.util.GraphFileUtil;
 
 public class FileReferenceFileImport extends SimanticsResourceFileImport {
 
-    private static final Map<String, String> ALLOWED_EXTENSIONS = Collections.singletonMap("*.asd", "All files");
+    private static final Map<String, String> ALLOWED_EXTENSIONS = Collections.singletonMap("*", "All files");
     
     @Override
-    public Optional<Resource> perform(Resource parent, Path file) {
-        try {
-            return Optional.of(GraphFileUtil.createFileReference(parent, file));
-        } catch (DatabaseException e) {
-            e.printStackTrace();
-            return Optional.empty();
-        }
+    public Optional<Resource> perform(Resource parent, Path file) throws Exception {
+        return Optional.of(GraphFileUtil.createFileReference(parent, file));
     }
 
     @Override
index 40deb1c148a7c5652ae0569d8e1606793b1d2c85..012c757c214c4a2914703fa6c6341e0ed6d185c8 100644 (file)
@@ -22,19 +22,14 @@ public class LibraryFolderFileImport extends SimanticsResourceFileImport {
     }
 
     @Override
-    public Optional<Resource> perform(Resource parent, Path file) {
+    public Optional<Resource> perform(Resource parent, Path file) throws Exception {
         final String name = file.getFileName().toString();
-        try {
-            return Optional.of(Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
+        return Optional.of(Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
 
-                @Override
-                public Resource perform(WriteGraph graph) throws DatabaseException {
-                    return ModelingUtils.createLibrary(graph, parent, name);
-                }
-            }));
-        } catch (DatabaseException e) {
-            e.printStackTrace();
-            return Optional.empty();
-        }
+            @Override
+            public Resource perform(WriteGraph graph) throws DatabaseException {
+                return ModelingUtils.createLibrary(graph, parent, name);
+            }
+        }));
     }
 }
index 74d2a0322f45c426e0fffa1434e888641e69632c..50fd584466bedd5849d950b9c778f80b16441fa3 100644 (file)
@@ -21,6 +21,8 @@ import org.simantics.fileimport.FileImportService;
 import org.simantics.fileimport.dropins.FileImportDropins;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * SCL interface for Simantics File Import Functionality
@@ -30,6 +32,8 @@ import org.simantics.utils.FileUtils;
  *
  */
 public class DropinsSCL {
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(DropinsSCL.class);
 
     public static void watchDropinsFolder() {
         FileImportDropins.watchDropinsFolder();
@@ -42,8 +46,9 @@ public class DropinsSCL {
     public static void uploadToDropinsBase64(String base64, String fileName) {
         // ensure that watcher is awake
         FileImportDropins.watchDropinsFolder();
+        Path rootFolder = null;
         try {
-            Path rootFolder = Activator.getDropinsFolder();
+            rootFolder = Activator.getDropinsFolder();
             Path newFile = rootFolder.resolve(fileName);
             if (Files.exists(newFile)) {
                 newFile = findFreshFileName(rootFolder, fileName);
@@ -51,7 +56,7 @@ public class DropinsSCL {
             byte[] bytes = Base64.decode(base64);
             FileUtils.writeFile(newFile.toFile(), bytes);
         } catch (IOException e) {
-            e.printStackTrace();
+            LOGGER.error("Could not upload base64 to file " + (rootFolder != null ? rootFolder.resolve(fileName).toAbsolutePath() : ""), e);
         }
     }
 
index 20eb07a6bbe8168cb9054da477e982b2dd27a8d6..f5ed551cca6c884930b20e07ea441e6005b88b4c 100644 (file)
@@ -11,8 +11,8 @@ Require-Bundle: org.eclipse.core.runtime,
  org.simantics.utils.thread,
  org.simantics.utils.thread.swt,
  org.simantics.utils.ui;bundle-version="1.0.0",
- javax.vecmath;bundle-version="1.0.0",
  org.apache.commons.collections;bundle-version="3.2.1",
+ org.apache.commons.math3,
  gnu.trove3;bundle-version="3.0.0",
  org.simantics.scenegraph;bundle-version="1.1.1";visibility:=reexport,
  org.simantics.threadlog;bundle-version="1.0.0";resolution:=optional,
index 17304ef3e548da3642672c21993c6f4e4042e6c8..2679ef620ac5c87b65de2337c9a188219895a88e 100644 (file)
@@ -81,6 +81,8 @@ public class AWTChassis extends JComponent implements ICanvasChassis {
     private transient boolean                    closed           = false;
     protected ICanvasContext                     canvasContext;
 
+    private boolean useVolatileImage = true;
+    
     // Marks the content dirty
     protected IContentListener contentListener = new IContentListener() {
         @Override
@@ -277,6 +279,14 @@ public class AWTChassis extends JComponent implements ICanvasChassis {
     public IHintContext getHintContext() {
         return hintCtx;
     }
+    
+    public void setUseVolatileImage(boolean useVolatileImage) {
+               this.useVolatileImage = useVolatileImage;
+       }
+    
+    public boolean isUseVolatileImage() {
+               return useVolatileImage;
+       }
 
     private void paintScenegraph(Graphics2D g2d, Rectangle controlBounds) {
         Color bg = getBackground();
@@ -355,7 +365,9 @@ public class AWTChassis extends JComponent implements ICanvasChassis {
             startmem = Runtime.getRuntime().freeMemory();
             start = System.nanoTime();
         }
-        VolatileImage buffer = paintToVolatileImage(g2d, b);
+        VolatileImage buffer = null;
+        if (useVolatileImage)
+               buffer = paintToVolatileImage(g2d, b);
         if (closed)
             return;
         if (DebugPolicy.PERF_CHASSIS_RENDER_FRAME) {
index 1eb15f61c2132ece167643ee6af6638ef4cb6e9b..d69ef69c69fadec257a3e07e2fc31a600cd5ed15 100644 (file)
@@ -557,6 +557,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
             ConnectionNode holder = e.getHint(sgKey);
             if (holder == null) {
                 holder = parentNode.addNode(ElementUtils.generateNodeId(e), ConnectionNode.class);
+                holder.setKey(e.getHint(ElementHints.KEY_OBJECT));
                 holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e));
                 e.setHint(sgKey, holder);
                 holder.setZIndex(parentNode.getNodeCount() + 1);
@@ -567,6 +568,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
             SingleElementNode holder = e.getHint(sgKey);
             if (holder == null) {
                 holder = parentNode.addNode(ElementUtils.generateNodeId(e), SingleElementNode.class);
+                holder.setKey(e.getHint(ElementHints.KEY_OBJECT));
                 holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e));
                 e.setHint(sgKey, holder);
                 holder.setZIndex(parentNode.getNodeCount() + 1);
index 1a12210f0912c23ccc2fbd1ea01fcdcb246a4e4a..74934321739daa9dc59e20ffa0f02a96ab25b65f 100644 (file)
@@ -1162,7 +1162,7 @@ public class ElementUtils {
             // If the previously available node is not a parent of the specified
             // node create a new node under the specified parent and set that
             // as the node of the specified element.
-            if (!node.getParent().equals(withParentNode)) {
+            if (!withParentNode.equals(node.getParent())) {
                 node = nodeId != null ? withParentNode.getOrCreateNode(nodeId, nodeClass) : withParentNode.addNode(nodeClass);
                 forElement.setHint(withNodeKey, node);
                 if (nodeCreationCallback != null)
index ca8518e6c38a5863267edb63b4f5336a01fdfe1b..f38e0a6c5910d08555783168e777b2f574bc224b 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 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
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - #7119 refactoring
  *******************************************************************************/
 package org.simantics.g2d.element.handler.impl;
 
@@ -30,10 +31,10 @@ import org.simantics.g2d.utils.geom.DirectionSet;
  */
 public class Terminals implements TerminalLayout, TerminalTopology {
 
-    private static final long             serialVersionUID = -6532093690907028016L;
+    private static final long serialVersionUID = -6532093690907028016L;
 
-    private final Map<Terminal, ObjectTerminal> terminalMap      = new THashMap<Terminal, ObjectTerminal>();
-    private final ArrayList<Terminal>           terminals        = new ArrayList<Terminal>();
+    protected final Map<Terminal, ObjectTerminal> terminalMap = new THashMap<>();
+    protected final ArrayList<Terminal>           terminals   = new ArrayList<>();
 
     public Terminals(Collection<ObjectTerminal> ts) {
         for (ObjectTerminal ti : ts) {
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/MonitorClass.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/MonitorClass.java
deleted file mode 100644 (file)
index 1f21ee8..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-///*******************************************************************************
-// * Copyright (c) 2007, 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.g2d.elementclass;
-//
-//import java.awt.BasicStroke;
-//import java.awt.Color;
-//import java.awt.Font;
-//import java.awt.FontMetrics;
-//import java.awt.Graphics2D;
-//import java.awt.Rectangle;
-//import java.awt.Shape;
-//import java.awt.event.ActionEvent;
-//import java.awt.event.ActionListener;
-//import java.awt.geom.AffineTransform;
-//import java.awt.geom.Path2D;
-//import java.awt.geom.Point2D;
-//import java.awt.geom.Rectangle2D;
-//import java.util.EnumSet;
-//import java.util.Map;
-//
-//import javax.vecmath.Vector2d;
-//
-//import org.simantics.g2d.diagram.IDiagram;
-//import org.simantics.g2d.element.ElementClass;
-//import org.simantics.g2d.element.ElementHints;
-//import org.simantics.g2d.element.ElementUtils;
-//import org.simantics.g2d.element.IElement;
-//import org.simantics.g2d.element.SceneGraphNodeKey;
-//import org.simantics.g2d.element.handler.ElementHandler;
-//import org.simantics.g2d.element.handler.FillColor;
-//import org.simantics.g2d.element.handler.InternalSize;
-//import org.simantics.g2d.element.handler.LifeCycle;
-//import org.simantics.g2d.element.handler.Move;
-//import org.simantics.g2d.element.handler.Outline;
-//import org.simantics.g2d.element.handler.Rotate;
-//import org.simantics.g2d.element.handler.Scale;
-//import org.simantics.g2d.element.handler.SceneGraph;
-//import org.simantics.g2d.element.handler.StaticSymbol;
-//import org.simantics.g2d.element.handler.Text;
-//import org.simantics.g2d.element.handler.TextEditor;
-//import org.simantics.g2d.element.handler.Transform;
-//import org.simantics.g2d.element.handler.TextEditor.Modifier;
-//import org.simantics.g2d.element.handler.impl.BorderColorImpl;
-//import org.simantics.g2d.element.handler.impl.FillColorImpl;
-//import org.simantics.g2d.element.handler.impl.SimpleElementLayers;
-//import org.simantics.g2d.element.handler.impl.StaticSymbolImpl;
-//import org.simantics.g2d.element.handler.impl.TextColorImpl;
-//import org.simantics.g2d.element.handler.impl.TextEditorImpl;
-//import org.simantics.g2d.element.handler.impl.TextFontImpl;
-//import org.simantics.g2d.element.handler.impl.TextImpl;
-//import org.simantics.g2d.image.Image;
-//import org.simantics.g2d.image.ProviderUtils;
-//import org.simantics.g2d.image.impl.AbstractImage;
-//import org.simantics.g2d.utils.Alignment;
-//import org.simantics.scenegraph.Node;
-//import org.simantics.scenegraph.g2d.G2DParentNode;
-//import org.simantics.scenegraph.g2d.nodes.MonitorNode;
-//import org.simantics.utils.datastructures.cache.IFactory;
-//import org.simantics.utils.datastructures.cache.IProvider;
-//import org.simantics.utils.datastructures.cache.ProvisionException;
-//import org.simantics.utils.datastructures.hints.IHintContext.Key;
-//import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
-//import org.simantics.utils.strings.format.MetricsFormat;
-//import org.simantics.utils.strings.format.MetricsFormatList;
-//
-///**
-// * @author Tuukka Lehtonen
-// */
-//public class MonitorClass {
-//
-//    static final Font        FONT                      = Font.decode("Helvetica 12");
-//
-//    /**
-//     * Back-end specific object describing the monitored component.
-//     */
-//    public static final Key  KEY_MONITOR_COMPONENT     = new KeyOf(Object.class, "MONITOR_COMPONENT");
-//
-//    /**
-//     * The valuation suffix string describing the monitored variable of the
-//     * component described by {@link #KEY_MONITOR_COMPONENT}.
-//     */
-//    public static final Key  KEY_MONITOR_SUFFIX        = new KeyOf(String.class, "MONITOR_SUFFIX");
-//
-//    public static final Key  KEY_MONITOR_SUBSTITUTIONS = new KeyOf(Map.class, "MONITOR_SUBSTITUTIONS");
-//    public static final Key  KEY_MONITOR_GC            = new KeyOf(Graphics2D.class, "MONITOR_GC");
-//    public static final Key  KEY_MONITOR_HEIGHT        = new KeyOf(Double.class, "MONITOR_HEIGHT");
-//    public static final Key  KEY_NUMBER_FORMAT         = new KeyOf(MetricsFormat.class, "NUMBER_FORMAT");
-//    public static final Key  KEY_TOOLTIP_TEXT          = new KeyOf(String.class, "TOOLTIP_TEXT");
-//
-//    /**
-//     * If this hint is defined, the monitor will force its x-axis to match this
-//     * angle. If this hint doesn't exist, the monitor will not force x-axis
-//     * orientation.
-//     */
-//    public static final Key  KEY_DIRECTION             = new KeyOf(Double.class, "MONITOR_DIRECTION");
-//
-//    public static final Key  KEY_BORDER_WIDTH          = new KeyOf(Double.class, "MONITOR_BORDER");
-//
-//    public static final Key  KEY_SG_NODE               = new SceneGraphNodeKey(Node.class, "MONITOR_SG_NODE");
-//
-//    final static BasicStroke STROKE                    = new BasicStroke(1.0f);
-//
-//    public final static Alignment DEFAULT_HORIZONTAL_ALIGN  = Alignment.CENTER;
-//    public final static Alignment DEFAULT_VERTICAL_ALIGN    = Alignment.CENTER;
-//    public final static MetricsFormat DEFAULT_NUMBER_FORMAT = MetricsFormatList.METRICS_DECIMAL;
-//
-//    public final static Color     DEFAULT_FILL_COLOR        = new Color(224, 224, 224);
-//    public final static Color     DEFAULT_BORDER_COLOR      = Color.BLACK;
-//
-//    public final static double    DEFAULT_HORIZONTAL_MARGIN = 5.0;
-//    public final static double    DEFAULT_VERTICAL_MARGIN   = 2.5;
-//
-//    static Alignment getHorizontalAlignment(IElement e) {
-//        return ElementUtils.getHintOrDefault(e, ElementHints.KEY_HORIZONTAL_ALIGN, DEFAULT_HORIZONTAL_ALIGN);
-//    }
-//
-//    static Alignment getVerticalAlignment(IElement e) {
-//        return ElementUtils.getHintOrDefault(e, ElementHints.KEY_VERTICAL_ALIGN, DEFAULT_VERTICAL_ALIGN);
-//    }
-//
-//    static MetricsFormat getNumberFormat(IElement e) {
-//        return ElementUtils.getHintOrDefault(e, KEY_NUMBER_FORMAT, DEFAULT_NUMBER_FORMAT);
-//    }
-//
-//    static void setNumberFormat(IElement e, MetricsFormat f) {
-//        ElementUtils.setOrRemoveHint(e, KEY_NUMBER_FORMAT, f);
-//    }
-//
-//    static double getHorizontalMargin(IElement e) {
-//        return DEFAULT_HORIZONTAL_MARGIN;
-//    }
-//
-//    static double getVerticalMargin(IElement e) {
-//        return DEFAULT_VERTICAL_MARGIN;
-//    }
-//
-//    static Font getFont(IElement e) {
-//        return ElementUtils.getHintOrDefault(e, ElementHints.KEY_FONT, FONT);
-//    }
-//
-//    public static class MonitorHandlerImpl implements MonitorHandler {
-//        private static final long          serialVersionUID = -4258875745321808416L;
-//        public static final MonitorHandler INSTANCE         = new MonitorHandlerImpl();
-//    }
-//
-//    static class Initializer implements LifeCycle {
-//        private static final long serialVersionUID = 4404942036933073584L;
-//
-//        IElement parentElement;
-//        Map<String, String> substitutions;
-//        Object component;
-//        String suffix;
-//        boolean hack;
-//
-//        Initializer(IElement parentElement, Map<String, String> substitutions, Object component, String suffix, boolean hack) {
-//            this.parentElement = parentElement;
-//            this.substitutions = substitutions;
-//            this.component = component;
-//            this.suffix = suffix;
-//            this.hack = hack;
-//        }
-//
-//        @Override
-//        public void onElementActivated(IDiagram d, IElement e) {
-//
-//            if(!hack) {
-//
-//                hack = true;
-//
-//                Point2D parentPos = ElementUtils.getPos(parentElement);
-//                Point2D thisPos = ElementUtils.getPos(e);
-//
-//                Move move = e.getElementClass().getSingleItem(Move.class);
-//                move.moveTo(e, thisPos.getX() - parentPos.getX(), thisPos.getY() - parentPos.getY());
-//
-//            }
-//
-//        }
-//        @Override
-//        public void onElementCreated(IElement e) {
-//            if(parentElement != null) e.setHint(ElementHints.KEY_PARENT_ELEMENT, parentElement);
-//            if(substitutions != null) e.setHint(KEY_MONITOR_SUBSTITUTIONS, substitutions);
-//            if(component != null) e.setHint(KEY_MONITOR_COMPONENT, component);
-//            if(suffix != null) e.setHint(KEY_MONITOR_SUFFIX, suffix);
-//
-//            e.setHint(KEY_DIRECTION, 0.0);
-//            e.setHint(KEY_NUMBER_FORMAT, DEFAULT_NUMBER_FORMAT);
-//            //e.setHint(KEY_HORIZONTAL_ALIGN, Alignment.LEADING);
-//            //e.setHint(KEY_VERTICAL_ALIGN, Alignment.LEADING);
-//        }
-//        @Override
-//        public void onElementDeactivated(IDiagram d, IElement e) {
-//        }
-//        @Override
-//        public void onElementDestroyed(IElement e) {
-//        }
-//    };
-//
-//    static String finalText(IElement e) {
-//        String text = e.getElementClass().getSingleItem(Text.class).getText(e);
-//        if (text == null)
-//            return null;
-//        return substitute(text, e);
-//    }
-//
-//    public static String editText(IElement e) {
-//        return substitute("#v1", e);
-//    }
-//
-//    private static String formValue(IElement e) {
-//        // TODO: consider using substitute
-//        Map<String, String> substitutions = e.getHint(KEY_MONITOR_SUBSTITUTIONS);
-//        if (substitutions != null) {
-//            String value = substitutions.get("#v1");
-//            if (substitutions.containsKey("#u1") && substitutions.get("#u1").length() > 0) {
-//                value += " " + substitutions.get("#u1");
-//            }
-//            return value;
-//        }
-//        return null;
-//    }
-//
-//    static String substitute(String text, IElement e) {
-//        Map<String, String> substitutions = e.getHint(KEY_MONITOR_SUBSTITUTIONS);
-//        return substitute(text, substitutions);
-//    }
-//
-//    static String substitute(String text, Map<String, String> substitutions) {
-//        if (substitutions != null) {
-//            // TODO: slow as hell
-//            for(Map.Entry<String, String> entry : substitutions.entrySet()) {
-//                if (entry.getValue() != null) {
-//                    text = text.replace(entry.getKey(), entry.getValue());
-//                } else {
-//                    text = text.replace(entry.getKey(), "<null>");
-//                }
-//            }
-//        }
-//        return text;
-//    }
-//
-//    public static void update(IElement e) {
-//        MonitorSGNode node = e.getElementClass().getSingleItem(MonitorSGNode.class);
-//        node.update(e);
-//    }
-//
-//    public static void cleanup(IElement e) {
-//        MonitorSGNode node = e.getElementClass().getSingleItem(MonitorSGNode.class);
-//        node.cleanup(e);
-//    }
-//
-//    static final Rectangle2D DEFAULT_BOX = new Rectangle2D.Double(0, 0, 0, 0);
-//
-//    static Shape createMonitor(IElement e) {
-//        Alignment hAlign = getHorizontalAlignment(e);
-//        Alignment vAlign = getVerticalAlignment(e);
-//        double hMargin = getHorizontalMargin(e);
-//        double vMargin = getVerticalMargin(e);
-//
-//        String text = finalText(e);
-//        if(text == null) {
-//            return align(hMargin, vMargin, hAlign, vAlign, DEFAULT_BOX);
-//        }
-//
-//        Graphics2D g = e.getHint(KEY_MONITOR_GC);
-//        if(g == null) {
-//            return align(hMargin, vMargin, hAlign, vAlign, DEFAULT_BOX);
-//        }
-//
-//        Font f = getFont(e);
-//        FontMetrics fm   = g.getFontMetrics(f);
-//        Rectangle2D rect = fm.getStringBounds(text, g);
-//
-//        return align(hMargin, vMargin, hAlign, vAlign, rect);
-//    }
-//
-//    static Shape align(double hMargin, double vMargin, Alignment hAlign, Alignment vAlign, Rectangle2D rect) {
-//        //System.out.println("align: " + hMargin + ", " + vMargin + ", " + hAlign + ", " + vAlign + ": " + rect);
-//        double tx = align(hMargin, hAlign, rect.getMinX(), rect.getMaxX());
-//        double ty = align(vMargin, vAlign, rect.getMinY(), rect.getMaxY());
-//        //System.out.println("    translate: " + tx + " "  + ty);
-//        double nw = rect.getWidth() + 2*hMargin;
-//        double nh = rect.getHeight() + 2*vMargin;
-//        return makePath(tx + rect.getMinX(), ty + rect.getMinY(), nw, nh);
-//    }
-//
-//    static double align(double margin, Alignment align, double min, double max) {
-//        double s = max - min;
-//        switch (align) {
-//            case LEADING:
-//                return -min;
-//            case TRAILING:
-//                return -s - 2 * margin - min;
-//            case CENTER:
-//                return -0.5 * s - margin - min;
-//            default:
-//                return 0;
-//        }
-//    }
-//
-//    static Path2D makePath(double x, double y, double w, double h) {
-//        Path2D path = new Path2D.Double();
-//        path.moveTo(x, y);
-//        path.lineTo(x+w, y);
-//        path.lineTo(x+w, y+h);
-//        path.lineTo(x, y+h);
-//        path.closePath();
-//        return path;
-//    }
-//
-//    public static final Shape BOX_SHAPE = new Rectangle(-1, -1, 2, 2);
-//
-//    public static class MonitorSGNode implements SceneGraph, InternalSize, Outline {
-//        private static final long serialVersionUID = -106278359626957687L;
-//
-//        static final MonitorSGNode INSTANCE = new MonitorSGNode();
-//
-//        @Override
-//        public void init(final IElement e, final G2DParentNode parent) {
-//            // Create node if it doesn't exist yet
-//            MonitorNode node = (MonitorNode)e.getHint(KEY_SG_NODE);
-//            if(node == null || node.getBounds() == null || node.getParent() != parent) {
-//                node = parent.addNode(ElementUtils.generateNodeId(e), MonitorNode.class);
-//                e.setHint(KEY_SG_NODE, node);
-//
-//                node.setActionListener(new ActionListener() {
-//                    @Override
-//                    public void actionPerformed(ActionEvent event) {
-//                        TextEditor editor = e.getElementClass().getAtMostOneItemOfClass(TextEditor.class);
-//                        if (editor != null) {
-//                            Modifier modifier = editor.getModifier(e);
-//                            if (modifier != null) {
-//                                String newValue = event.getActionCommand();
-//                                String error = modifier.isValid(e, newValue);
-//
-//                                if (error == null) {
-//                                    // Only modify if the modification was not
-//                                    // cancelled and the value is valid.
-//                                    modifier.modify(e, newValue);
-//                                } else {
-//                                    // TODO: show error somehow, possibly through status bar
-//
-//                                    // Make sure that the monitor content gets
-//                                    // reset to its previous value.
-//                                    MonitorNode node = e.getHint(KEY_SG_NODE);
-//                                    if (node != null)
-//                                        node.setText(formValue(e));
-//                                }
-//                            }
-//                        }
-//
-////                        final Text t = e.getElementClass().getAtMostOneItemOfClass(Text.class);
-////                        t.setText(e, event.getActionCommand()); // FIXME
-//                    }});
-//                node.setSize(50, 22);
-//                Double border_width = (Double)e.getHint(KEY_BORDER_WIDTH);
-//                if(border_width == null) border_width = 0.1;
-//                
-//                node.setBorderWidth(border_width);
-//
-//                Rectangle2D bounds = (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);
-//                if(bounds != null) node.setBounds(bounds);
-//            }
-//            update(e);
-//        }
-//
-//        public void update(IElement e) {
-//            String value = null;
-//
-//            final Text t = e.getElementClass().getAtMostOneItemOfClass(Text.class);
-//            assert(t != null);
-//
-//            value = formValue(e);
-//
-//            MonitorNode node = (MonitorNode) e.getHint(KEY_SG_NODE);
-//            if (node != null && value != null) {
-//                node.setText(value);
-//                Object component = e.getHint(KEY_MONITOR_COMPONENT);
-//                if (component != null) {
-//                    node.setEditable(true);
-//                } else {
-//                    node.setEditable(false);
-//                }
-//
-//                // FIXME: set only if changed .. (but quickfix is not to clone)
-//                Font font = ElementUtils.getTextFont(e);
-//                if (node.getFont() != font) { // Don't update if we have a same object
-//                    node.setFont(font);
-//                }
-//                Color color = ElementUtils.getTextColor(e);
-//                node.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()));
-//                String tt = (String) e.getHint(KEY_TOOLTIP_TEXT);
-//                if (tt != null)
-//                    node.setToolTipText(new String(tt));
-//            }
-//        }
-//
-//        @Override
-//        public void cleanup(IElement e) {
-//            MonitorNode node = (MonitorNode)e.removeHint(KEY_SG_NODE);
-//            if (node != null)
-//                node.remove();
-//        }
-//
-//        @Override
-//        public Rectangle2D getBounds(IElement e, Rectangle2D size) {
-//            Rectangle2D shape = new Rectangle2D.Double(0, 0, 0, 0);
-//
-//            MonitorNode node = (MonitorNode)e.getHint(KEY_SG_NODE);
-//            if(node != null && node.getBounds() != null) {
-//                shape = node.getBounds().getBounds2D();
-//            }
-//
-//            if(size != null) size.setRect(shape);
-//            return shape;
-//        }
-//
-//        @Override
-//        public Shape getElementShape(IElement e) {
-//            Shape shape = new Rectangle2D.Double(0, 0, 0, 0);
-//
-//            MonitorNode node = (MonitorNode)e.getHint(KEY_SG_NODE);
-//            if(node != null && node.getBounds() != null) {
-//                shape = node.getBounds();
-//            }
-//
-//            return shape;
-//        }
-//
-//    }
-//
-//    public static class Transformer implements Transform, Move, Rotate, Scale, LifeCycle {
-//
-//        private static final long serialVersionUID = -3704887325602085677L;
-//
-//        public static final Transformer INSTANCE = new Transformer(null);
-//
-//        Double aspectRatio;
-//
-//        public Transformer() {
-//            this(null);
-//        }
-//
-//        public Transformer(Double aspectRatio) {
-//            this.aspectRatio = aspectRatio;
-//        }
-//
-//        @Override
-//        public Double getFixedAspectRatio(IElement e) {
-//            return aspectRatio;
-//        }
-//
-//        @Override
-//        public Point2D getScale(IElement e) {
-//            AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
-//            return _getScale(at);
-//        }
-//
-//        @Override
-//        public void setScale(IElement e, Point2D newScale) {
-//            // Doesn't work for monitors.
-//            Point2D oldScale = getScale(e);
-//            double sx = newScale.getX() / oldScale.getX();
-//            double sy = newScale.getY() / oldScale.getY();
-//            AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
-//            at = new AffineTransform(at);
-//            at.scale(sx, sy);
-//            e.setHint(ElementHints.KEY_TRANSFORM, at);
-//        }
-//
-//        @Override
-//        public Point2D getMaximumScale(IElement e) {
-//            return null;
-//        }
-//
-//        @Override
-//        public Point2D getMinimumScale(IElement e) {
-//            return null;
-//        }
-//
-//        private static Point2D _getScale(AffineTransform at) {
-//            double m00 = at.getScaleX();
-//            double m11 = at.getScaleY();
-//            double m10 = at.getShearY();
-//            double m01 = at.getShearX();
-//            // Project unit vector to canvas
-//            double sx = Math.sqrt(m00 * m00 + m10 * m10);
-//            double sy = Math.sqrt(m01 * m01 + m11 * m11);
-//            return new Point2D.Double(sx, sy);
-//        }
-//
-//        @Override
-//        public void rotate(IElement e, double theta, Point2D origin) {
-//            if (Double.isNaN(theta)) return;
-//            theta = Math.toDegrees(theta);
-//            Double angle = e.getHint(KEY_DIRECTION);
-//            double newAngle = angle != null ? angle+theta : theta;
-//            newAngle = Math.IEEEremainder(newAngle, 360.0);
-//            e.setHint(KEY_DIRECTION, newAngle);
-//        }
-//
-//        @Override
-//        public double getAngle(IElement e) {
-//            Double angle = e.getHint(KEY_DIRECTION);
-//            return angle != null ? Math.toRadians(angle) : 0;
-//        }
-//
-//        @Override
-//        public Point2D getPosition(IElement e) {
-//            AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
-//            Point2D p = new Point2D.Double(at.getTranslateX(), at.getTranslateY());
-//            return p;
-//        }
-//
-//        @Override
-//        public void moveTo(IElement e, double x, double y) {
-//            AffineTransform origAt = e.getHint(ElementHints.KEY_TRANSFORM);
-//            double oldX = origAt.getTranslateX();
-//            double oldY = origAt.getTranslateY();
-//            AffineTransform move = AffineTransform.getTranslateInstance(x-oldX, y-oldY);
-//            AffineTransform at2 = new AffineTransform(origAt);
-//            at2.preConcatenate(move);
-//            e.setHint(ElementHints.KEY_TRANSFORM, at2);
-//        }
-//
-//        @Override
-//        public AffineTransform getTransform(IElement e) {
-//            AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
-//
-//            IElement parentElement = e.getHint(ElementHints.KEY_PARENT_ELEMENT);
-//            if (parentElement == null)
-//                return at;
-//
-//            Transform parentTransform = parentElement.getElementClass().getSingleItem(Transform.class);
-//            assert(parentTransform!=null);
-//
-//            AffineTransform result = (AffineTransform)at.clone();
-//            result.preConcatenate(parentTransform.getTransform(parentElement));
-//
-//            return result;
-//        }
-//
-//        @Override
-//        public void setTransform(IElement e, AffineTransform at) {
-//            e.setHint(ElementHints.KEY_TRANSFORM, at.clone());
-//        }
-//
-//        @Override
-//        public void onElementActivated(IDiagram d, IElement e) {
-//        }
-//
-//        @Override
-//        public void onElementCreated(IElement e) {
-//            e.setHint(ElementHints.KEY_TRANSFORM, new AffineTransform());
-//        }
-//
-//        @Override
-//        public void onElementDeactivated(IDiagram d, IElement e) {
-//        }
-//
-//        @Override
-//        public void onElementDestroyed(IElement e) {
-////            List<SceneGraph> nodeHandlers = e.getElementClass().getItemsByClass(SceneGraph.class);
-////            for(SceneGraph n : nodeHandlers) {
-////                System.out.println("element gone:"+e);
-////                n.cleanup(e);
-////            }
-//        }
-//    }
-//
-//    static double getOrientationDelta(IElement e, AffineTransform tr) {
-//        Double angle = e.getHint(KEY_DIRECTION);
-//        if (angle == null || Double.isNaN(angle))
-//            return Double.NaN;
-//        double angrad = Math.toRadians(angle);
-//
-//        Vector2d forcedAxis = new Vector2d(Math.cos(angrad), Math.sin(angrad));
-//        Vector2d x = new Vector2d(tr.getScaleX(), tr.getShearX());
-//        forcedAxis.normalize();
-//        x.normalize();
-//        double cosa = forcedAxis.dot(x);
-//        double delta = Math.acos(cosa);
-//        return delta;
-//    }
-//
-//    static class MonitorImageFactory implements IFactory<Image> {
-//        private double staticScaleX = 1, staticScaleY = 1;
-//
-//        public MonitorImageFactory(double staticScaleX, double staticScaleY) {
-//            this.staticScaleX = staticScaleX;
-//            this.staticScaleY = staticScaleY;
-//        }
-//
-//        @Override
-//        public Image get() throws ProvisionException {
-//            return new AbstractImage() {
-//                Shape path = align(DEFAULT_HORIZONTAL_MARGIN, DEFAULT_VERTICAL_MARGIN, DEFAULT_HORIZONTAL_ALIGN, DEFAULT_VERTICAL_ALIGN,
-//                        new Rectangle2D.Double(0, 0, 50*staticScaleX, 22*staticScaleY));
-//
-//                @Override
-//                public Rectangle2D getBounds() {
-//                    return path.getBounds2D();
-//                }
-//
-//                @Override
-//                public EnumSet<Feature> getFeatures() {
-//                    return EnumSet.of(Feature.Vector);
-//                }
-//
-//                @Override
-//                public Shape getOutline() {
-//                    return path;
-//                }
-//
-//                @Override
-//                public Node init(G2DParentNode parent) {
-//                    MonitorNode node = parent.getOrCreateNode(""+hashCode(), MonitorNode.class);
-//                    node.setText("");
-//                    node.setSize(50, 22);
-//                    node.setBorderWidth(1);
-//                    node.setText("Drop Me");
-//                    node.setTransform(AffineTransform.getScaleInstance(staticScaleX, staticScaleY));
-//                    return node;
-//                }
-//            };
-//        }
-//    }
-//
-//    static final IProvider<Image> MONITOR_IMAGE =
-//        ProviderUtils.reference(
-//                ProviderUtils.cache(
-//                        ProviderUtils.rasterize(
-//                                new MonitorImageFactory(0.5, 0.5)
-//                        )));
-//
-//    static final StaticSymbol MONITOR_SYMBOL = new StaticSymbolImpl( MONITOR_IMAGE.get() );
-//
-//    static final FillColor FILL_COLOR = new FillColorImpl(DEFAULT_FILL_COLOR);
-//
-//    public static final ElementClass MONITOR_CLASS =
-//        ElementClass.compile(
-//                MonitorHandlerImpl.INSTANCE,
-//                Transformer.INSTANCE,
-//                BorderColorImpl.BLACK,
-//                FILL_COLOR,
-//                MonitorSGNode.INSTANCE,
-//                TextImpl.INSTANCE,
-//                TextEditorImpl.INSTANCE,
-//                TextFontImpl.DEFAULT,
-//                TextColorImpl.BLACK,
-//                SimpleElementLayers.INSTANCE,
-//                MONITOR_SYMBOL
-//        );
-//
-//    // staticScale{X,Y} define the scale of the static monitor image
-//    public static ElementClass create(IElement parentElement, Map<String, String> substitutions, Object component, String suffix, double staticScaleX, double staticScaleY, ElementHandler... extraHandlers) {
-//        // Bit of a hack to be able to define the scale
-//        IProvider<Image> staticMonitorSymbolProvider = ProviderUtils.reference(
-//                ProviderUtils.cache(
-//                        ProviderUtils
-//                        .rasterize(
-//                                new MonitorImageFactory(staticScaleX, staticScaleY))));
-//        StaticSymbol staticMonitorSymbol = new StaticSymbolImpl( staticMonitorSymbolProvider.get() );
-//        return ElementClass.compile(
-//                new Initializer(parentElement, substitutions, component, suffix, parentElement != null ? false : true),
-//                MonitorHandlerImpl.INSTANCE,
-//                Transformer.INSTANCE,
-//                BorderColorImpl.BLACK,
-//                FILL_COLOR,
-//                MonitorSGNode.INSTANCE,
-//                TextImpl.INSTANCE,
-//                TextEditorImpl.INSTANCE,
-//                TextFontImpl.DEFAULT,
-//                TextColorImpl.BLACK,
-//                SimpleElementLayers.INSTANCE,
-//                staticMonitorSymbol
-//        ).newClassWith(extraHandlers);
-//    }
-//
-//}
index 01d60e58fc01f7e4cbf91bdb8bf9da397cb0e811..f364f5040b05a908bd4bbdc04109ab1fd85eb08d 100644 (file)
@@ -14,9 +14,8 @@ package org.simantics.g2d.elementclass.wheel;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
-import javax.vecmath.Vector2d;
-import javax.vecmath.Vector3d;
-
+import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.element.ElementHints;
@@ -52,7 +51,7 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
 
        public static final RotatorHandler INSTANCE = new RotatorHandler(); 
        
-       public static final double STRAY_DISTANCE = 1000;       
+       public static final double STRAY_DISTANCE = 1000;
        
        public double initial_friction = 0.20;
        public double initial_grab_friction = 0.99;
@@ -63,8 +62,8 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
        /** Angular velocity, canvas specific variable */
        public static final Key KEY_ANG_VEL = new KeyOf(Double.class);
        /** Minimum number of pointers */
-       public static final Key KEY_MIN_POINTERS = new KeyOf(Integer.class);    
-       public static final Key KEY_GRAB_FRICTION = new KeyOf(Double.class);    
+       public static final Key KEY_MIN_POINTERS = new KeyOf(Integer.class);
+       public static final Key KEY_GRAB_FRICTION = new KeyOf(Double.class);
        public static final Key KEY_FRICTION = new KeyOf(Double.class);
        public static final Key KEY_FACTOR = new KeyOf(Double.class);
 
@@ -75,50 +74,46 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
        @Override
        protected void onDrag(GrabInfo gi, ICanvasContext ctx) {
                IElement        e       = gi.e;
-               Point2D origo   = getOrigo(e, null);            
+               Point2D origo   = getOrigo(e, null);
                Point2D prevPos = gi.prevPosElement;
                Point2D p               = gi.dragPosElement;
                
-               // ---- Wheel is held! ----             
+               // ---- Wheel is held! ----
                // position vector 0
-               Vector2d p0 = new Vector2d(prevPos.getX(), prevPos.getY());
+               Vector2D p0 = new Vector2D(prevPos.getX(), prevPos.getY());
                // position vector 1
-               Vector2d p1 = new Vector2d(p.getX(), p.getY());
+               Vector2D p1 = new Vector2D(p.getX(), p.getY());
                // motion vector
-               Vector2d f = new Vector2d(p1);
-               f.sub(p0);
+               Vector2D f = p1.subtract(p0);
                // no movement
-               if (f.length()==0) return;
+               if (f.getNormSq()==0) return;
                
                // -- We are holding the wheel and we have moved the pointer --
 
                // vector from origo to mouse
-               Vector2d odp0 = new Vector2d(p0.x - origo.getX(), p0.y - origo.getY());
-               Vector2d odp1 = new Vector2d(p1.x - origo.getX(), p1.y - origo.getY());
+               Vector2D odp0 = new Vector2D(p0.getX() - origo.getX(), p0.getY() - origo.getY());
+               Vector2D odp1 = new Vector2D(p1.getX() - origo.getX(), p1.getY() - origo.getY());
                // convert motion into tangential and normal vectors            
                // normal vector of the motion
-               Vector2d fn = new Vector2d(odp0);
-               fn.scale( f.dot(odp0) / odp0.lengthSquared() );
+               Vector2D fn = odp0.scalarMultiply( f.dotProduct(odp0) / odp0.getNormSq() );
                // tangential vector of the motion
-               Vector2d ft = new Vector2d(f);
-               ft.sub(fn);
+               Vector2D ft = f.subtract(fn);
                
                // momentum             
-               Vector3d r = new Vector3d(odp0.x, odp0.y, 0);
-               Vector3d F = new Vector3d(ft.x, ft.y, 0);
-               Vector3d M = new Vector3d();
-               M.cross(r, F);
+               Vector3D r = new Vector3D(odp0.getX(), odp0.getY(), 0);
+               Vector3D F = new Vector3D(ft.getX(), ft.getY(), 0);
+               Vector3D M = r.crossProduct(F);
                if (!isGrabbed(e, ctx)) return;
                
                // Turn the wheel
-               double deltaAngle = odp0.angle(odp1);
-               if (M.z<0) deltaAngle *= -1;
+               double deltaAngle = Vector2D.angle(odp0, odp1);
+               if (M.getZ()<0) deltaAngle *= -1;
                
                double deltaAngularVelocity = deltaAngle * 20;
                setAngVel(e, getAngVel(e)+deltaAngularVelocity);
 
                deltaAngle *= 0.297;
-               modifyValue(e, ctx, deltaAngle);                                
+               modifyValue(e, ctx, deltaAngle);
        }
 
        @Override
@@ -172,7 +167,7 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
                double dt = ((double)deltaTime)/1000;
                angVel *= Math.pow(1-f, dt);
                setAngVel(e, angVel);
-               ctx.getContentContext().setDirty();             
+               ctx.getContentContext().setDirty();
        }
 
        @Override
@@ -262,11 +257,11 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
        
        public void setAngVel(IElement e, double value)
        {
-               e.setHint(KEY_ANG_VEL, value);          
+               e.setHint(KEY_ANG_VEL, value);
        }
        
        public boolean isGrabbed(IElement e, ICanvasContext ctx) {
-           return (getGrabCount(e, ctx)>=getMinPointers(e)) || !isEnabled(e);      
+           return (getGrabCount(e, ctx)>=getMinPointers(e)) || !isEnabled(e);
        }
        
        public boolean isMoving(IElement e) {
@@ -286,8 +281,6 @@ public class RotatorHandler extends AbstractGrabbable implements HandleMouseEven
        
        public boolean isMoveable(IElement e) {
                return true;
-       }               
+       }
 
-       
-       
 }
index a36315698ce642203d25fc938c50f3f68c7ee477..f23f742cd0cd176a356933a280532d8a03c70a8c 100644 (file)
@@ -22,15 +22,13 @@ import org.simantics.g2d.image.DefaultImages;
  */
 public class WheelClass {
 
-       public static final ElementClass WHEEL = 
-               ElementClass.compile(
-                               // Pick missing
-                               DefaultTransform.INSTANCE,
-                       new RotatorHandler(),
-                       new PaintableSymbolHandler(DefaultImages.WHEEL),
-                       Stateful.ENABLED_BY_DEFAULT                     
-                               );
-       
+       public static final ElementClass WHEEL =
+                       ElementClass.compile(
+                                       // Pick missing
+                                       DefaultTransform.INSTANCE,
+                                       new RotatorHandler(),
+                                       new PaintableSymbolHandler(DefaultImages.WHEEL),
+                                       Stateful.ENABLED_BY_DEFAULT
+                                       );
 
-       
 }
diff --git a/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/resourceFiles/FilterCRWriter.java b/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/resourceFiles/FilterCRWriter.java
new file mode 100644 (file)
index 0000000..2e96675
--- /dev/null
@@ -0,0 +1,47 @@
+package org.simantics.graph.compiler.internal.resourceFiles;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+public class FilterCRWriter extends FilterWriter {
+
+    public FilterCRWriter(Writer out) {
+        super(out);
+    }
+    
+    @Override
+    public void write(int c) throws IOException {
+        if(c != '\r')
+            out.write(c);
+    }
+    
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        int begin = 0;
+        for(int i=0;i<len;++i) {
+            if(cbuf[off+i] == '\r') {
+                if(i > begin)
+                    write(cbuf, off+begin, i-begin);
+                begin = i+1;
+            }
+        }
+        if(len > begin)
+            write(cbuf, off+begin, len-begin);
+    }
+    
+    @Override
+    public void write(String str, int off, int len) throws IOException {
+        int begin = 0;
+        for(int i=0;i<len;++i) {
+            if(str.charAt(off+i) == '\r') {
+                if(i > begin)
+                    write(str, off+begin, i-begin);
+                begin = i+1;
+            }
+        }
+        if(len > begin)
+            write(str, off+begin, len-begin);
+    }
+
+}
index 25758343d59751d3dd2a5d28d2aac8d950485ebe..a847dbee130e61fb4ab6ea84a17afa14020ee9f8 100644 (file)
@@ -6,6 +6,7 @@ import java.io.OutputStreamWriter;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.net.URL;
+import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -19,6 +20,8 @@ import freemarker.template.DefaultObjectWrapper;
 import freemarker.template.Template;
 
 public class ResourceFile implements IResourceFile {
+    private final static Charset UTF8 = Charset.forName("UTF-8");
+    
        String packageName;
        String className;
        List<ResourceRef> resources;
@@ -88,8 +91,8 @@ public class ResourceFile implements IResourceFile {
        @Override
        public InputStream getContent() {
                StringWriter writer = new StringWriter();
-               write(writer);
-               return new ByteArrayInputStream(writer.toString().getBytes());
+               write(String.format("%n").length() == 1 ? new FilterCRWriter(writer) : writer);
+               return new ByteArrayInputStream(writer.toString().getBytes(UTF8));
        }
        
        /* (non-Javadoc)
@@ -105,11 +108,12 @@ public class ResourceFile implements IResourceFile {
        }
        
        public static void main(String[] args) {
-               ResourceRef Foo = new ResourceRef("Foo", "http://www.dsf.sdf/Foo");
+               /*ResourceRef Foo = new ResourceRef("Foo", "http://www.dsf.sdf/Foo");
                ResourceRef Bar = new ResourceRef("Foo", "http://www.dsf.sdf/Bar");
                Bar.deprecated = true;
                new ResourceFile("org.simantics.graph", "Testi", Arrays.<ResourceRef>asList(
                                Foo, Bar
-                       )).write(new OutputStreamWriter(System.out));
+                       )).write(new OutputStreamWriter(System.out));*/
+           System.out.println(String.format("%n").length());
        }
 }
index 3e15e4b3141647ac1a21a042049a5cdbb057ce8a..b641490326b4be2c7874cd47d939b6210413f9dc 100644 (file)
@@ -28,6 +28,10 @@ public class CoreInitialization {
        }
 
        static {
+               // IMPORTANT NOTICE:
+               // DO NOT alter the order of these definitions in any way
+               // unless you deliberately want to make the system incompatible
+               // with databases that have been created before changing these.
                addLayer0Builtin("InstanceOf");
                addLayer0Builtin("Inherits");
                addLayer0Builtin("SubrelationOf");
@@ -49,8 +53,33 @@ public class CoreInitialization {
                addLayer0Builtin("HasPredicateInverse");
                addLayer0Builtin("HasObject");
 
-               addBuiltin("http://Projects");
+               // #7016: This bogus URI replaces the builtin entry
+               // that was originally http://Projects.
+               //
+               // addBuiltin("http://Projects") was removed because its existence
+               // resulted in a non-functioning URI space because:
+               //
+               // 1. http://Projects was added as a "built-in resource" when the database
+               //    is first initialized which means that ReadGraph.getResource("http://Projects")
+               //    would succeed even when the resource was not yet properly imported
+               //    from the project ontology.
+               //
+               // 2. When the project ontology is imported, a new resource is
+               //    created to represent http://Projects instead of using the existing
+               //    uninitialized "built-in resource". The L0.ExternalEntity changes made
+               //    to the standard transferable graph import in this patch caused the
+               //    code to find the built-in resource for "http://Projects" and think
+               //    that it has to be a resource that's already properly initialized.
+               //    This led to the TG import not initializing the resource at all.
+               //    Previously there was a bug here as well but it was hidden by the fact
+               //    that the system would import the actual/new "http://Projects"
+               //    resource from the ontology anyway. This effectively left the
+               //    uninitialized built-in resource just hanging in the database as
+               //    trash.
+               //addBuiltin("http://Projects");
+               addBuiltin("75e23fb39121b4b37cf2e6a26ccb34c52f77522d-do-not-remove");
                addBuiltin("http:/");
+               addLayer0Builtin("ExternalEntity");
        }
 
     public static void initializeBuiltins(Session session) throws DatabaseException {
diff --git a/bundles/org.simantics.graph.db/src/org/simantics/graph/db/ImportResult.java b/bundles/org.simantics.graph.db/src/org/simantics/graph/db/ImportResult.java
new file mode 100644 (file)
index 0000000..1d986da
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semamtum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.graph.db;
+
+import java.util.Set;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class ImportResult {
+
+       /**
+        * This lists externals that the import was missing and has created in the
+        * database as L0.ExternalEntity place-holders for now.
+        */
+       public final Set<String> missingExternals;
+
+       public ImportResult(Set<String> missingExternals) {
+               this.missingExternals = missingExternals;
+       }
+
+       public boolean hasMissingExternals() {
+               return !missingExternals.isEmpty();
+       }
+
+}
index 48cebf342c2cfe5566a3fb325bd33994437b20f7..3599eefc0ecc81c9cb6d012bf31415f48bcfc34f 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2016 Association for Decentralized Information Management
+ * Copyright (c) 2012, 2017 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
@@ -8,17 +8,16 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
- *     Semantum Oy
+ *     Semantum Oy - e.g. #7016
  *******************************************************************************/
 package org.simantics.graph.db;
 
 import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -30,6 +29,7 @@ import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.serialization.Serializer;
 import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.util.URIStringUtils;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
@@ -45,6 +45,7 @@ import org.simantics.db.service.ClusterBuilder2;
 import org.simantics.db.service.ClusterBuilderFactory;
 import org.simantics.db.service.ClusteringSupport;
 import org.simantics.db.service.SerialisationSupport;
+import org.simantics.db.service.XSupport;
 import org.simantics.graph.db.TransferableGraphSource.TransferableGraphSourceProcedure;
 import org.simantics.graph.db.TransferableGraphSource.TransferableGraphSourceValueProcedure;
 import org.simantics.graph.representation.Extensions;
@@ -57,37 +58,15 @@ import org.simantics.graph.representation.Root;
 import org.simantics.graph.representation.TransferableGraphUtils;
 import org.simantics.graph.utils.TGResourceUtil;
 import org.simantics.graph.utils.TGResourceUtil.LongAdapter;
+import org.simantics.utils.datastructures.Pair;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
 
 public class StreamingTransferableGraphImportProcess implements TransferableGraphImporter {
-       
-       public static String LOG_FILE = "transferableGraphs.log";
-       final static private boolean LOG = false;
-       
-       static DataOutput log;
 
-       static {
-
-               if (LOG) {
-                       
-                       try {
-                               FileOutputStream stream = new FileOutputStream(LOG_FILE);
-                               log = new DataOutputStream(stream);
-                       } catch (FileNotFoundException e) {
-                               e.printStackTrace();
-                       }
-               }
-
-       }
-       
-       private static void log(String line) {
-               if (LOG) {
-                       try {
-                               log.writeUTF(line + "\n");
-                       } catch (IOException e) {
-                               e.printStackTrace();
-                       }
-               }
-       }
+       private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StreamingTransferableGraphImportProcess.class);
 
        Resource indexRoot;
        TransferableGraphSource tg;
@@ -95,32 +74,36 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
        IImportAdvisor2 advisor;
        ClusterBuilder2 builder;
        final TGResourceUtil resourceUtil = new TGResourceUtil();
-       
+
        int[] handles;
-       
-       Set<String> missingExternals = new HashSet<String>(); 
-       
+
+       Map<String,Integer> allMissingExternals = new HashMap<>();
+       Set<String> missingExternals = new HashSet<>();
+       Map<String,Resource> resolvedParents = new HashMap<>();
+       TIntObjectHashMap<Resource> existingInternalMap = new TIntObjectHashMap<>();
+
        int resourceCount;
        Identity[] identities;
        TreeMap<String, Variant> extensions;
-       
+
        // Builtins
        Resource RootLibrary;
        Resource String;
+       Resource ExternalEntity;
        Resource Library;
-       
+
        Resource InstanceOf;
        Resource ConsistsOf;
        Resource PartOf;
        Resource HasName;
        Resource NameOf;        
-                               
+
        public StreamingTransferableGraphImportProcess(Session session, VirtualGraph vg, TransferableGraphSource tg, IImportAdvisor2 advisor) {
                this.tg = tg;
                this.vg = vg;
                this.advisor = advisor;
        }
-       
+
        public void readIdentities(ReadGraph g) throws Exception {
                extensions = tg.getExtensions();
                resourceCount = tg.getResourceCount();
@@ -135,7 +118,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                        }
                });
        }
-       
+
        public void findBuiltins(WriteOnlyGraph g) throws DatabaseException {
                RootLibrary = g.getBuiltin("http:/");
                String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
@@ -145,8 +128,9 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
                HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
                NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
+               ExternalEntity = g.getBuiltin(CoreInitialization.LAYER0 + "ExternalEntity");
        }
-       
+
        public void findBuiltins(ReadGraph g) throws DatabaseException {
                RootLibrary = g.getBuiltin("http:/");
                String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
@@ -156,59 +140,18 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
                HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
                NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
+               ExternalEntity = g.getBuiltin(CoreInitialization.LAYER0 + "ExternalEntity");
        }
 
-//     /* Preparation that is used when the core is empty. 
-//      */
-//     void initialPrepare(WriteOnlyGraph graph) throws DatabaseException {
-//             findBuiltins(graph);
-//             
-//             resources = new Resource[tg.resourceCount];
-//             
-//             int Root = -1;
-//             int SimanticsDomain = -1;
-//             int Layer0 = -1;
-//             
-//             for(Identity identity : tg.identities) {
-//                     if(identity.definition instanceof Internal) {
-//                             Internal def = (Internal)identity.definition;
-//                             Resource res = null;
-//                             if(def.parent == Layer0) {
-//                                     try {
-//                                             res = graph.getBuiltin(CoreInitialization.LAYER0 + def.name);
-//                                     } catch(ResourceNotFoundException e) {                                                                          
-//                                     }
-//                             }
-//                             else if(def.parent == SimanticsDomain) {
-//                                     if(def.name.equals("Layer0-1.0"))
-//                                             Layer0 = identity.resource;
-//                             }
-//                             else if(def.parent == Root) {
-//                                     if(def.name.equals("www.simantics.org"))
-//                                             SimanticsDomain = identity.resource;
-//                             }
-//
-//                             if(res == null)
-//                                     res = createChild(graph, resources[def.parent], def.name);
-//                             else
-//                                     createChild(graph, res, resources[def.parent], def.name);
-//                             resources[identity.resource] = res;
-//                     }
-//                     else if(identity.definition instanceof Root) {
-//                             Root = identity.resource;
-//                             resources[identity.resource] = RootLibrary;                             
-//                     } 
-//             }
-//     }
-       
-       void addMissing(String external) {
-               Set<String> removals = new HashSet<String>();
+       void addMissing(int handleIndex, String external) {
+               allMissingExternals.put(external, handleIndex);
+               Set<String> removals = new HashSet<>();
                for(String ext : missingExternals) if(ext.startsWith(external)) return;
                for(String ext : missingExternals) if(external.startsWith(ext)) removals.add(ext);
                missingExternals.removeAll(removals);
                missingExternals.add(external);
        }
-       
+
        void prepare(ReadGraph graph) throws Exception {
 
                Resource target = advisor.getTarget();
@@ -225,7 +168,8 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                ClusterBuilderFactory factory = graph.getService(ClusterBuilderFactory.class);
                ClusterBuilder2 builder = factory.create(vg, false);
                
-        this.handles = new int[resourceCount];
+               this.handles = new int[resourceCount];
+               TIntObjectMap<Identity> identityMap = TransferableGraphUtils.mapIdentities(identities);
                
                for(Identity identity : identities) {
                        IdentityDefinition definition = identity.definition;
@@ -243,23 +187,28 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                                                Resource parent = handle != 0 ? builder.resource(handle) : null;
                                                // TODO: escape should be removed when names become well-behaving
                                                if(parent != null) {
+                                                       resolvedParents.put(graph.getURI(parent), parent);
                                                    Map<String,Resource> childMap = graph
                                            .syncRequest(new UnescapedChildMapOfResource(parent),
-                                                   new TransientCacheAsyncListener<Map<String, Resource>>()); 
+                                                   TransientCacheAsyncListener.instance()); 
                                                        Resource child = childMap.get(def.name); 
                                                        if(child == null) {
-                                                               addMissing(graph.getURI(parent) + "/" + def.name);
+                                                               addMissing(identity.resource, graph.getURI(parent) + "/" + def.name);
                                                        } else {
                                                                handles[identity.resource] = builder.handle(child);
                                                        }
                                                } else {
-                                                   addMissing(TransferableGraphUtils.getURI(resourceCount, identities, def.parent) + "/" + def.name);
+                                                   addMissing(identity.resource, TransferableGraphUtils.getURI(resourceCount, identityMap, def.parent) + "/" + def.name);
                                                }
                                        }
                                }
                        }
                        else if(definition instanceof Internal) {
-                               // Do not do anything for now
+                               String uri = TransferableGraphUtils.getURI(resourceCount, identityMap, identity.resource);
+                               Resource existing = graph.getPossibleResource(uri);
+                               if(existing != null) {
+                                       existingInternalMap.put(identity.resource, existing);
+                               }
                        }
                        else if(definition instanceof Root) {
                                Root root = (Root)definition;
@@ -279,7 +228,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                        }
                }               
                
-               if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);
+               //if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);
                
        }
 
@@ -292,7 +241,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                graph.claim(child, HasName, NameOf, nameResource);
                return child;
        }
-       
+
        int[] getClustering() {
                Variant v = extensions.get(Extensions.CLUSTERING);
                if(v == null) return null;
@@ -318,7 +267,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
        boolean needTranslation(Datatype type) {
            return resourceUtil.mayHaveResource(type);
        }
-       
+
        void findClusterSet(WriteOnlyGraph graph, Resource rootLibrary, int[] clustering, int[] clusterSets, long[] clusters, int id) throws DatabaseException {
                ClusteringSupport support = graph.getService(ClusteringSupport.class);
                if(id == Extensions.ROOT_LIBRARY_CLUSTER_SET || id == Extensions.INDEX_ROOT_CLUSTER_SET) return;
@@ -352,11 +301,47 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                        }
                }
        }
-       
+
+       void createMissing(final WriteOnlyGraph graph) throws Exception {
+               
+               if(allMissingExternals.isEmpty()) return;
+               
+               XSupport xs = graph.getService(XSupport.class);
+               Pair<Boolean,Boolean> serviceMode = xs.getServiceMode();
+               xs.setServiceMode(true, false);
+               try {
+                       ArrayList<String> missing = new ArrayList<>(allMissingExternals.keySet());
+                       Collections.sort(missing);
+                       for(String uri : missing) {
+                               String[] parts = URIStringUtils.splitURI(uri);
+
+                               Resource parent = resolvedParents.get(parts[0]);
+                               // TODO: proper exception message
+                               if(parent == null) throw new IllegalStateException("!!");
+
+                               Resource childResource = graph.newResource();
+                               graph.claim(childResource, InstanceOf, null, ExternalEntity);
+
+                               Resource nameResource = graph.newResource();
+                               graph.claim(nameResource, InstanceOf, null, String);
+                               graph.claimValue(nameResource, parts[1], WriteBindings.STRING);
+                               graph.claim(childResource, HasName, NameOf, nameResource);
+
+                               graph.claim(parent, ConsistsOf, PartOf, childResource);
+
+                               resolvedParents.put(uri, childResource);
+
+                               handles[allMissingExternals.get(uri)] = builder.handle(childResource);
+                       }
+               } finally {
+                       xs.setServiceMode(serviceMode.first, serviceMode.second);
+               }
+       }
+
        void write(final WriteOnlyGraph graph) throws Exception {
         
         final SerialisationSupport ss = graph.getService(SerialisationSupport.class);
-           
+        
         ClusterBuilderFactory factory = graph.getService(ClusterBuilderFactory.class);
         if(advisor instanceof IImportAdvisor2) {
             boolean allowImmutable = ((IImportAdvisor2)advisor).allowImmutableModifications();
@@ -365,6 +350,8 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
             builder = factory.create(vg, false);
         }
         
+        createMissing(graph);
+        
                final int[] handles = this.handles; 
                
                int[] clustering = getClustering();
@@ -439,10 +426,17 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                        }
                        else if(definition instanceof Internal) {
                                Internal def = (Internal)definition;
-                               if(handles[identity.resource] != 0)
-                                       handles[identity.resource] = builder.handle(advisor.createChild(graph, this, builder.resource(handles[def.parent]), builder.resource(handles[identity.resource]), def.name));
-                               else
-                                       handles[identity.resource] = builder.handle(advisor.createChild(graph, this, builder.resource(handles[def.parent]), null, def.name));
+                               
+                               Resource external = existingInternalMap.get(identity.resource);
+                               if(external != null) {
+                                       handles[identity.resource] = builder.handle(external);
+                               } else {
+                                       if(handles[identity.resource] != 0)
+                                               handles[identity.resource] = builder.handle(advisor.createChild(graph, this, builder.resource(handles[def.parent]), builder.resource(handles[identity.resource]), def.name));
+                                       else
+                                               handles[identity.resource] = builder.handle(advisor.createChild(graph, this, builder.resource(handles[def.parent]), null, def.name));
+                               }
+                               
                        }
                        else if(definition instanceof Root) {
                                
@@ -492,7 +486,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                }); 
                
                tg.getValueCount();
-
+               
                class ValueProcedure extends InputStream implements TransferableGraphSourceValueProcedure {
 
             private TGResourceUtil util = new TGResourceUtil();
@@ -541,7 +535,7 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                 try {
                     builder.appendValue(value);
                 } catch (DatabaseException e) {
-                    e.printStackTrace();
+                    LOGGER.error("Failed to write value into database", e);
                 }
                 return value;
             }
@@ -558,8 +552,12 @@ public class StreamingTransferableGraphImportProcess implements TransferableGrap
                
                tg.forValues2(null, new ValueProcedure());
                
+               for(Resource r : existingInternalMap.valueCollection()) {
+                       graph.deny(r, InstanceOf, null, ExternalEntity, null);
+               }
+               
        }
-       
+
        @Override
        public long[] getResourceIds(SerialisationSupport serializer) throws DatabaseException {
                final int count = handles.length;
index bdfd3de6e2ae326ad739468ac913f1f58fcbe274..6aa24637e4a075792121eace6f5b81447d722e6a 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.TreeMap;
 import java.util.UUID;
+import java.util.function.BiFunction;
 
 import org.simantics.databoard.Accessors;
 import org.simantics.databoard.Bindings;
@@ -61,7 +62,6 @@ import org.simantics.graph.representation.External;
 import org.simantics.graph.representation.Identity;
 import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.graph.representation.Value;
-import org.simantics.utils.datastructures.BinaryFunction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -154,7 +154,7 @@ public class TransferableGraphs {
                                session.getService(SerialisationSupport.class));
        }
 
-       public static void importGraph1(Session session, final TransferableGraph1 tg, IImportAdvisor advisor, final BinaryFunction<Boolean, WriteOnlyGraph, TransferableGraphImportProcess> callback) throws DatabaseException, TransferableGraphException {
+       public static void importGraph1(Session session, final TransferableGraph1 tg, IImportAdvisor advisor, final BiFunction<WriteOnlyGraph, TransferableGraphImportProcess, Boolean> callback) throws DatabaseException, TransferableGraphException {
                final TransferableGraphImportProcess process = new TransferableGraphImportProcess(tg, 
                                advisor == null ? new ImportAdvisor() : advisor);
                session.syncRequest(new ReadRequest() {
@@ -168,20 +168,20 @@ public class TransferableGraphs {
                        public void perform(WriteOnlyGraph graph) throws DatabaseException {
                                process.write(graph);
                                if(callback != null)
-                                       callback.call(graph, process);
+                                       callback.apply(graph, process);
                        }
                });
        }
 
-    public static void importGraph1(Session session, final TransferableGraphSource tg, IImportAdvisor advisor) throws Exception {
-        importGraph1(session, tg, advisor, null);
+    public static ImportResult importGraph1(Session session, final TransferableGraphSource tg, IImportAdvisor advisor) throws Exception {
+        return importGraph1(session, tg, advisor, null);
     }
 
-    public static void importGraph1(Session session, final TransferableGraphSource tg, IImportAdvisor advisor, TGStatusMonitor monitor) throws DatabaseException {
-        importGraph1(session, null, tg, advisor, monitor);
+    public static ImportResult importGraph1(Session session, final TransferableGraphSource tg, IImportAdvisor advisor, TGStatusMonitor monitor) throws DatabaseException {
+        return importGraph1(session, null, tg, advisor, monitor);
     }
 
-    public static void importGraph1(Session session, VirtualGraph vg, final TransferableGraphSource tg, IImportAdvisor advisor_, TGStatusMonitor monitor) throws DatabaseException {
+    public static ImportResult importGraph1(Session session, VirtualGraph vg, final TransferableGraphSource tg, IImportAdvisor advisor_, TGStatusMonitor monitor) throws DatabaseException {
         
         final IImportAdvisor2 advisor = (advisor_ instanceof IImportAdvisor2) ? ((IImportAdvisor2)advisor_) : new WrapperAdvisor(advisor_);
 
@@ -210,6 +210,8 @@ public class TransferableGraphs {
                                }
                        }
                });
+
+               return new ImportResult(process.missingExternals);
        }
 
        public static void importGraph1WithMonitor(Session session, final TransferableGraph1 tg, IImportAdvisor advisor_, TGStatusMonitor monitor) throws DatabaseException {
@@ -235,7 +237,7 @@ public class TransferableGraphs {
                });
        }
 
-       public static void importGraph1WithChanges(Session session, final TransferableGraph1 tg, IImportAdvisor advisor, final BinaryFunction<Boolean, WriteGraph, TransferableGraphImportProcess> callback) throws DatabaseException, TransferableGraphException {
+       public static void importGraph1WithChanges(Session session, final TransferableGraph1 tg, IImportAdvisor advisor, final BiFunction<WriteGraph, TransferableGraphImportProcess, Boolean> callback) throws DatabaseException, TransferableGraphException {
                final TransferableGraphImportProcess process = new TransferableGraphImportProcess(tg, 
                                advisor == null ? new ImportAdvisor() : advisor);
                session.syncRequest(new ReadRequest() {
@@ -252,7 +254,7 @@ public class TransferableGraphs {
                 comments.add("Imported transferable graph with " + tg.resourceCount + " resources");
                 graph.addMetadata(comments);
                                if(callback != null)
-                                       callback.call(graph, process);
+                                       callback.apply(graph, process);
                        }
                });
        }
index 2d786a580cc70437f2975a70548418c9921122ce..4786abd3b6d30aaa8ea0250e09a814c280cf9e0f 100644 (file)
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.simantics.graph.db.old;
 
+import java.util.function.BiFunction;
+
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Session;
 import org.simantics.db.WriteGraph;
@@ -22,11 +24,10 @@ import org.simantics.graph.db.IImportAdvisor;
 import org.simantics.graph.db.ImportAdvisor;
 import org.simantics.graph.db.TransferableGraphException;
 import org.simantics.graph.representation.old.OldTransferableGraph1;
-import org.simantics.utils.datastructures.BinaryFunction;
 
 public class OldTransferableGraphs {
 
-    public static void importGraph1(Session session, final OldTransferableGraph1 tg, IImportAdvisor advisor, final BinaryFunction<Boolean, WriteOnlyGraph, OldTransferableGraphImportProcess1> callback) throws DatabaseException, TransferableGraphException {
+    public static void importGraph1(Session session, final OldTransferableGraph1 tg, IImportAdvisor advisor, final BiFunction<WriteOnlyGraph, OldTransferableGraphImportProcess1, Boolean> callback) throws DatabaseException, TransferableGraphException {
         final OldTransferableGraphImportProcess1 process = new OldTransferableGraphImportProcess1(tg, 
                 advisor == null ? new ImportAdvisor() : advisor);
         session.syncRequest(new ReadRequest() {
@@ -40,7 +41,7 @@ public class OldTransferableGraphs {
             public void perform(WriteOnlyGraph graph) throws DatabaseException {
                 process.write(graph);
                 if(callback != null)
-                    callback.call(graph, process);
+                    callback.apply(graph, process);
             }
         });
     }
index 55b9cbe2efb4164a4091b36595217037b8b539d5..9882048b788144c74de9ac5ec56b69f6954ff384 100644 (file)
@@ -1,7 +1,9 @@
 package org.simantics.graph.refactoring;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
+import org.simantics.databoard.util.URIStringUtils;
 import org.simantics.graph.query.Path;
 import org.simantics.graph.query.PathChild;
 import org.simantics.graph.query.TransferableGraphConversion;
@@ -17,9 +19,11 @@ import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.graph.representation.TransferableGraphUtils;
 import org.simantics.graph.representation.old.OldTransferableGraph1;
 import org.simantics.graph.representation.old.OldValue1;
+import org.simantics.graph.store.GraphStore;
 import org.simantics.graph.store.IdentityStore;
 
 import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntIntHashMap;
 import gnu.trove.set.hash.TIntHashSet;
 
 public class GraphRefactoringUtils {
@@ -89,6 +93,20 @@ public class GraphRefactoringUtils {
         
     }
     
+    private static Identity recursePath(TransferableGraph1 tg, String path) {
+       
+       Identity extId = TransferableGraphUtils.findExternal(tg, path);
+       if(extId != null) return extId;
+       if("http://".equals(path)) return TransferableGraphUtils.findRootWithName(tg, "");
+       String[] parts = URIStringUtils.splitURI(path);
+       Identity parentId = recursePath(tg, parts[0]);
+       tg.identities = Arrays.copyOf(tg.identities, tg.identities.length+1);
+       Identity childIdentity = new Identity(tg.resourceCount++, new External(parentId.resource, parts[1]));
+               tg.identities[tg.identities.length-1] = childIdentity;
+               return childIdentity;
+       
+    }
+    
     public static void fixOntologyRoot(TransferableGraph1 tg, boolean tryToFix) {
 
        Identity[] ids = tg.identities;
@@ -97,37 +115,36 @@ public class GraphRefactoringUtils {
             if(id.definition instanceof Root) {
                 Root ext = (Root)id.definition;
                 if(ext.name.startsWith("http://")) {
-                       String rootName = ext.name.substring(ext.name.lastIndexOf("/")+1);
-                       String path = ext.name.substring(0, ext.name.lastIndexOf("/"));
-                       Identity pathId = TransferableGraphUtils.findExternal(tg, path);
-                       System.err.println("GraphRefactoringUtils.rootName=" + rootName);
-                       System.err.println("GraphRefactoringUtils.path2=" + path);
-                       if(pathId == null) {
-                               if(!tryToFix) return;
-                               IdentityStore idStore = TransferableGraphConversion.extractIdentities(tg);
-                               idStore.createPathToId(UriUtils.uriToPath(path));
-                               tg.resourceCount = idStore.getResourceCount();
-                               tg.identities = idStore.toArray();
-                               fixOntologyRoot(tg, false);
-                               return;
-                       } else {
-                               id.definition = new Internal(pathId.resource, rootName);
-                               TIntArrayList stms = new TIntArrayList(tg.statements);
-                       Identity consistsOf = TransferableGraphUtils.findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
-                       Identity partOf = TransferableGraphUtils.findExternal(tg, "http://www.simantics.org/Layer0-1.1/PartOf");
-                               stms.add(id.resource);
-                               stms.add(partOf.resource);
-                               stms.add(consistsOf.resource);
-                               stms.add(pathId.resource);
-                               tg.statements = stms.toArray();
-                               return;
-                       }
+                       
+                       String[] parts = URIStringUtils.splitURI(ext.name);
+                       Identity path = recursePath(tg, parts[0]);
+                       id.definition = new Internal(path.resource, parts[1]);
+                       
+                       GraphStore store = TransferableGraphConversion.convert(tg);
+                       int rootId = store.identities.createPathToId(UriUtils.uriToPath(ext.name));
+                       propagateNewMarks(store.identities, rootId);
+
+                       TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
+                               
+                       tg.resourceCount = tgNew.resourceCount;
+                       tg.identities = tgNew.identities;
+                       tg.values = tgNew.values;
+                       tg.statements = tgNew.statements;
+                               
+                       return;
                        
                 }
             }
         }
        
     }
+    
+       private static void propagateNewMarks(IdentityStore identities, int resource) {
+               if(identities.markNew(resource)) {
+                       for(int child : identities.getChildren(resource))
+                               propagateNewMarks(identities, child);
+               }
+       }
 
     public static void unfixIncorrectRoot(Identity[] ids) {
         for(int i=0;i<ids.length;++i) {
diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java
new file mode 100644 (file)
index 0000000..5968b68
--- /dev/null
@@ -0,0 +1,302 @@
+package org.simantics.graph.representation;
+
+import java.io.BufferedInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.TreeMap;
+
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.container.DataContainers;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.set.hash.TLongHashSet;
+
+/**
+ * @author Antti Villberg
+ * @since 1.24.0
+ */
+public class PrettyPrintTG extends TransferableGraphUtils {
+
+       int blankCounter = 0;
+       
+       StringBuilder output = new StringBuilder();
+       
+       static class ResourceInfo {
+               final boolean hasURI;
+               final String name;
+               final int resource;
+               boolean newResource = false;
+               int owner = 0;
+               int ownerPredicate = 0;
+               TIntArrayList owned = new TIntArrayList();
+               TIntArrayList statements = new TIntArrayList();
+               public ResourceInfo(boolean hasURI, String name, int resource) {
+                       this.hasURI = hasURI;
+                       this.name = name;
+                       this.resource = resource;
+               }
+       }
+       
+       TIntObjectHashMap<ResourceInfo> infos = new TIntObjectHashMap<>();
+       
+       ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName) {
+               String name = parentName + ".\"" + getName(parent) + "\"";
+               ResourceInfo info = new ResourceInfo(true, name, parent.resource); 
+               infos.put(parent.resource, info);
+               for(Identity child : getChildren(graph, parent)) {
+                       recurseURI(graph, child, name);
+               }
+               return info;
+       }
+       
+       void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) {
+               TIntArrayList statements = getStatements(graph, resource);
+               for(int i=0;i<statements.size();i+=2) {
+                       int object = statements.get(i+1);
+                       Identity objectId = getIdentity(graph, object);
+                       if(objectId != null) {
+                               if(objectId.definition instanceof External) continue;
+                       }
+                       ResourceInfo existing = infos.get(object);
+                       if(existing == null) {
+                               existing = new ResourceInfo(false, "blank" + blankCounter++, object);
+                               infos.put(object, existing);
+                               todo.add(object);
+                       }
+               }
+       }
+       
+       void discoverOwners(TransferableGraph1 graph, ResourceInfo info) {
+               int resource = info.resource;
+               TIntArrayList statements = getStatements(graph, resource);
+               for(int i=0;i<statements.size();i+=2) {
+                       int predicate = statements.get(i);
+                       int object = statements.get(i+1);
+                       ResourceInfo existing = infos.get(object);
+                       if(existing == null) continue;
+                       if(existing.owner == 0) {
+                               existing.owner = resource;
+                               existing.ownerPredicate = predicate;
+                               //System.err.println("First owner " + info.name + " => " + predicateURI + " " + existing.name);
+                       } else {
+                               existing.owner = -1;
+                               //System.err.println("Multiple owners " + info.name + " => " + predicateURI + " " + existing.name);
+                       }
+               }
+               info.statements = statements;
+       }
+       
+       void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) {
+               Identity id = getIdentity(graph, info.resource);
+               if(id == null) return;
+               if(id.definition instanceof Internal) {
+                       Identity instanceOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/InstanceOf");
+                       Identity library = findExternal(graph, "http://www.simantics.org/Layer0-1.1/Library");
+                       info.statements.add(instanceOf.resource);
+                       info.statements.add(library.resource);
+               }
+       }
+       
+       public static String getExternalURI(TransferableGraph1 tg, External ext) {
+               String name = ext.name;
+               if(name.contains(" ")) name = name.replace(" ", "_").replaceAll("@", "_");//name = "\"" + name + "\"";
+               int parentId = ext.parent;
+               if(parentId == 0) return ext.name;
+               else {
+                       Identity id = getIdentity(tg, parentId);
+                       if(id.definition instanceof External) {
+                               return getExternalURI(tg, (External)id.definition) + "/" + name;
+                       } else if(id.definition instanceof Root) {
+                               Root root = (Root)id.definition;
+                               return "http:/" + root.name + "/" + name; 
+                       } else {
+                               return null;
+                       }
+               }
+       }
+
+       public static String getExternalURI(TransferableGraph1 tg, int resource) {
+               Identity id = getIdentity(tg, resource);
+               if(id == null) return null;
+               if(id.definition instanceof External) {
+                       External ext = (External)id.definition;
+                       return getExternalURI(tg, ext);
+               }
+               return null;
+       }
+       
+       String rewritePredicateURI(TransferableGraph1 graph, int predicate) {
+               String uri = getExternalURI(graph, predicate);
+               if(uri == null) return null;
+               uri = uri.replace("http://www.simantics.org/Modeling-1.2", "MOD");
+               uri = uri.replace("http://www.simantics.org/Layer0-1.1", "L0");
+               uri = uri.replace("http://www.simantics.org/Layer0X-1.1", "L0X");
+               uri = uri.replace("http://www.simantics.org/Diagram-2.2", "DIA");
+               uri = uri.replace("http://www.simantics.org/Structural-1.2", "STR");
+               uri = uri.replace("http://www.simantics.org/Documentation-1.2", "DOCU");
+               uri = uri.replace("http://www.simantics.org/Document-1.2", "DOC");
+               uri = uri.replace("http://www.simantics.org/G2D-1.1", "G2D");
+               uri = uri.replace("http://www.simantics.org/Image2-1.2", "IMAGE2");
+               uri = uri.replace("http://www.simantics.org/SelectionView-1.2", "SEL");
+               uri = uri.replace("http://www.simantics.org/GraphFile-0.1", "GRAPHFILE");
+               uri = uri.replace("http://www.semantum.fi/Simupedia-1.0", "SIMUPEDIA");
+               uri = uri.replace("http://www.semantum.fi/SimupediaWorkbench-1.0", "SIMUPEDIA_WB");
+               uri = uri.replace("http://www.apros.fi/OperationUI-6.6", "APROS_OPER");
+               uri = uri.replace("http://semantum.fi/SimupediaStandardLibrary@1.3-trunk", "SIMUPEDIA_STD");
+               uri = uri.replace("/", ".");
+               return uri;
+       }
+       
+       void printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info) {
+               
+               if(info.hasURI) return;
+               output.append("  " + predicateURI2 + " " + info.name + "\n");
+               
+               Value value = findValue(graph, info.resource);
+               if(value != null) {
+                       
+               }
+               
+//             for(int i=0;i<info.owned.size();i+=2) {
+//                     String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
+//                     ResourceInfo ownedInfo = infos.get(info.owned.get(i+1));
+//                     if(ownedInfo == null) {
+//                             System.err.println("null owned");
+//                             continue;
+//                     }
+//                     printBlank(graph, predicateURI, ownedInfo);
+//             }
+               
+       }
+       
+       long longStm(int predicate, int object) {
+        return (predicate<<32) | (object & 0xffffffffL); 
+       }
+       
+       void printURI(TransferableGraph1 graph, ResourceInfo info) {
+               if(!info.hasURI) return;
+               if("ROOT".equals(info.name)) {
+                       output.append("ROOT=<http:/>\n");
+               } else {
+                       output.append(info.name + "\n");
+               }
+               if(info.newResource)
+                       output.append("  @L0.new\n");
+               TLongHashSet processed = new TLongHashSet();
+               for(int i=0;i<info.owned.size();i+=2) {
+                       String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
+                       ResourceInfo ownedInfo = infos.get(info.owned.get(i+1));
+                       if(ownedInfo == null) {
+                               System.err.println("null owned");
+                               continue;
+                       }
+                       long stmId = longStm(info.owned.get(i), info.owned.get(i+1));
+                       processed.add(stmId);
+                       printBlank(graph, predicateURI, ownedInfo);
+               }
+               Identity consistsOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
+               for(int i=0;i<info.statements.size();i+=2) {
+                       long stmId = longStm(info.statements.get(i), info.statements.get(i+1));
+                       if(processed.contains(stmId)) continue;
+                       if(consistsOf.resource == info.statements.get(i)) continue;
+                       String predicateURI = rewritePredicateURI(graph, info.statements.get(i));
+                       ResourceInfo objectInfo = infos.get(info.statements.get(i+1));
+                       if(objectInfo == null) {
+                               String objectURI = rewritePredicateURI(graph, info.statements.get(i+1));
+                               output.append("  " + predicateURI + " " + objectURI + "\n");
+                       } else {
+                               output.append("  " + predicateURI + " " + objectInfo.name + "\n");
+                       }
+               }
+       }
+
+       void prettyPrint(Path input, Path output) throws Exception {
+               System.out.format("Converting exported shared ontology%n\t" + input.toString() + "%nto bundle-compatible ontology%n\t" + output.toString());
+               try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128*1024)) {
+                       DataInput dis = new DataInputStream(is);
+                       org.simantics.databoard.container.DataContainer container = 
+                                       DataContainers.readFile(dis); 
+                       Binding binding = TransferableGraph1.BINDING;
+                       TransferableGraph1 graph = (TransferableGraph1)container.content.getValue(binding);
+                       // Discover resources with URI
+                       for(Identity id : TransferableGraphUtils.getRoots(graph)) {
+                               String name = "ROOT";
+                               ResourceInfo info = new ResourceInfo(true, name, id.resource); 
+                               infos.put(id.resource, info);
+                               for(Identity child : getChildren(graph, id)) {
+                                       ResourceInfo childInfo = recurseURI(graph, child, name);
+                                       childInfo.newResource = true;
+                               }
+                       }
+                       // Discover other resources
+                       TIntArrayList todo = new TIntArrayList();
+                       for(ResourceInfo info : infos.valueCollection())
+                               todo.add(info.resource);
+                       while(!todo.isEmpty()) {
+                               int resource = todo.removeAt(todo.size()-1);
+                               discoverBlank(graph, resource, todo);
+                       }
+                       for(ResourceInfo info : infos.valueCollection())
+                               discoverOwners(graph, info);
+                       for(ResourceInfo info : infos.valueCollection())
+                               fixInstanceOf(graph, info);
+                       for(ResourceInfo info : infos.valueCollection())
+                               if(info.owner > 0) {
+                                       ResourceInfo ownerInfo = infos.get(info.owner);
+                                       ownerInfo.owned.add(info.ownerPredicate);
+                                       ownerInfo.owned.add(info.resource);
+                               } else if (info.owner == 0) {
+                                       //System.err.println("faf1");
+                               } else if (info.owner == -1) {
+                                       //System.err.println("faf2");
+                               }
+                       
+                       TreeMap<String,ResourceInfo> order = new TreeMap<>();
+                       for(ResourceInfo info : infos.valueCollection())
+                               order.put(info.name, info);
+                       
+                       this.output.append("MOD = <http://www.simantics.org/Modeling-1.2>\n");
+                       this.output.append("L0 = <http://www.simantics.org/Layer0-1.1>\n");
+                       this.output.append("L0X = <http://www.simantics.org/Layer0X-1.1>\n");
+                       this.output.append("DIA = <http://www.simantics.org/Diagram-2.2>\n");
+                       this.output.append("STR = <http://www.simantics.org/Structural-1.2>\n");
+                       this.output.append("DOCU = <http://www.simantics.org/Documentation-1.2>\n");
+                       this.output.append("DOC = <http://www.simantics.org/Document-1.2>\n");
+                       this.output.append("G2D = <http://www.simantics.org/G2D-1.1>\n");
+                       this.output.append("SEL = <http://www.simantics.org/SelectionView-1.2>\n");
+                       this.output.append("IMAGE2 = <http://www.simantics.org/Image2-1.2>\n");
+                       this.output.append("GRAPHFILE = <http://www.simantics.org/GraphFile-0.1>\n");
+                       this.output.append("APROS_OPER = <http://www.apros.fi/OperationUI-6.6>\n");
+                       this.output.append("SIMUPEDIA = <http://www.semantum.fi/Simupedia-1.0>\n");
+                       this.output.append("SIMUPEDIA_WB = <http://www.semantum.fi/SimupediaWorkbench-1.0>\n");
+                       this.output.append("SIMUPEDIA_STD = <http://semantum.fi/SimupediaStandardLibrary@1.3-trunk>\n");
+                       
+//                     uri = uri.replace("http://semantum.fi/SimupediaStandardLibrary@1.3-trunk/", "SIMUPEDIA_STD.");
+
+                       
+                       for(ResourceInfo info : order.values())
+                               printURI(graph, info);
+                       
+                       Files.write(output, this.output.toString().getBytes());
+                               
+               }
+       }
+
+       public static void main(String[] args) throws Exception {
+               if (args.length < 1) {
+                       System.out.println("Required arguments: <input .sharedOntology file> [<output .tg file>]");
+               } else if (args.length < 2) {
+                       Path input = Paths.get(args[0]);
+                       Path output = input.getParent().resolve(input.getName(input.getNameCount()-1) + ".fixed");
+                       new PrettyPrintTG().prettyPrint(input, output);
+               } else {
+                       new PrettyPrintTG().prettyPrint(Paths.get(args[0]), Paths.get(args[1]));
+               }
+       }
+
+}
index 82ac178fbdca32113993e7b2201ec2a81377aa71..4646116dc37d784255466ad55f1914e94c545596 100644 (file)
@@ -4,6 +4,14 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.TreeMap;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.adapter.AdaptException;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
 
 public class TransferableGraphUtils {
 
@@ -67,36 +75,89 @@ public class TransferableGraphUtils {
                
        }
        
+       public static Identity getIdentity(TransferableGraph1 tg, int resource) {
+               for(Identity id : tg.identities) {
+                       if(id.resource == resource) return id;
+               }
+               return null;
+       }
+       
+       public static TIntArrayList getStatements(TransferableGraph1 tg, int resource) {
+               TIntArrayList result = new TIntArrayList();
+               for(int i=0;i<tg.statements.length;i+=4) {
+                       if(tg.statements[i] == resource) {
+                               result.add(tg.statements[i+1]);
+                               result.add(tg.statements[i+3]);
+                       }
+               }
+               return result;
+       }
+       
        public static Collection<Identity> getChildren(TransferableGraph1 tg, Identity parent) {
-               ArrayList<Identity> result = new ArrayList<Identity>();
-               System.err.println("children for " + parent.resource);
+               TreeMap<String,Identity> result = new TreeMap<>();
                for(Identity id : tg.identities) {
                        if(id.definition instanceof Internal) {
                                Internal internal = (Internal)id.definition;
-                               System.err.println("internal with parent " + internal.parent);
-                               if(internal.parent == parent.resource) result.add(id);
+                               if(internal.parent == parent.resource) result.put(internal.name, id);
+                       }
+               }
+               Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
+               Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
+               for(int i=0;i<tg.statements.length;i+=4) {
+                       if(tg.statements[i] == parent.resource) {
+                               if(tg.statements[i+1] == consistsOf.resource) {
+                                       Identity identity = getIdentity(tg, tg.statements[i+3]);
+                                       if(identity != null) {
+                                               if(identity.definition instanceof Internal) {
+                                                       Internal internal = (Internal)identity.definition;
+                                                       result.put(internal.name, identity);
+                                               }
+                                       } else {
+                                               int possibleNameResource = getPossibleObject(tg, tg.statements[i+3], hasName);
+                                               if(possibleNameResource != 0) {
+                                                       Value value = findValue(tg, possibleNameResource);
+                                                       if(value != null) {
+                                                               try {
+                                                                       String name = (String)value.value.getValue(Bindings.STRING);
+                                                                       result.put(name, new Identity(tg.statements[i+3], new Internal(tg.statements[i], name)));
+                                                               } catch (AdaptException e) {
+                                                                       e.printStackTrace();
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
                        }
                }
-               findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
+               return result.values();
+       }
+       
+       public static TIntArrayList getObjects(TransferableGraph1 tg, int subject, Identity predicate) {
+               TIntArrayList result = new TIntArrayList();
                for(int i=0;i<tg.statements.length;i+=4) {
-                       if(tg.statements[i] == parent.resource)
-                               System.err.println("related to parent  " + tg.statements[i+3]);
+                       if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
+                               result.add(tg.statements[i+3]);
+                       }
                }
                return result;
        }
        
-       public static int getPossibleObject(TransferableGraph1 tg, Identity subject, String predicate) {
-               Identity p = findExternal(tg, predicate);
-               if(p == null) return 0;
+       public static int getPossibleObject(TransferableGraph1 tg, int subject, Identity predicate) {
                int result = 0;
                for(int i=0;i<tg.statements.length;i+=4) {
-                       if(tg.statements[i] == subject.resource && tg.statements[i+1] == p.resource) {
+                       if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
                                if(result != 0) return 0;
                                result = tg.statements[i+3];
                        }
                }
                return result;
        }
+       
+       public static int getPossibleObject(TransferableGraph1 tg, Identity subject, String predicate) {
+               Identity p = findExternal(tg, predicate);
+               if(p == null) return 0;
+               return getPossibleObject(tg, subject.resource, p);
+       }
 
        public static Map<Identity, String> getNames(TransferableGraph1 tg, Collection<Identity> ids) {
                Map<Identity, String> result = new HashMap<Identity, String>();
@@ -159,11 +220,11 @@ public class TransferableGraphUtils {
                        else return getURI(resourceCount, identities, def.parent) + "/" + def.name;
                    } else if(definition instanceof Root) {
                        Root def = (Root)definition;
+                       if(def.name.isEmpty()) return "http:/";
                        return def.name;
                    } else if (definition instanceof Internal) {
                        Internal def = (Internal)definition;
-                       System.err.println("External URI error: parent was internal '" + def.name + "'");
-                       return "";
+                       return getURI(resourceCount, identities, def.parent) + "/" + def.name;
                    } else {
                        return "";
                    }
@@ -171,5 +232,39 @@ public class TransferableGraphUtils {
            }       
            return "<internal reference " + id + ">:";
        }
-       
+
+       public static TIntObjectMap<Identity> mapIdentities(TransferableGraph1 tg) {
+               return mapIdentities(tg.identities);
+       }
+
+       public static TIntObjectMap<Identity> mapIdentities(Identity[] identities) {
+               // Integer.MIN_VALUE cannot be the value of Identity.resource
+               TIntObjectMap<Identity> map = new TIntObjectHashMap<>(identities.length, 0.5f, Integer.MIN_VALUE);
+               for (Identity id : identities)
+                       map.put(id.resource, id);
+               return map;
+       }
+
+       public static String getURI(int resourceCount, TIntObjectMap<Identity> identities, int id) {
+               Identity identity = identities.get(id);
+               if(identity != null) {
+                       IdentityDefinition definition = identity.definition;
+                       if(definition instanceof External) {
+                               External def = (External)definition;
+                               if(def.parent == -1) return "http:/";
+                               else return getURI(resourceCount, identities, def.parent) + "/" + def.name;
+                       } else if(definition instanceof Root) {
+                               Root def = (Root)definition;
+                               if(def.name.isEmpty()) return "http:/";
+                               return def.name;
+                       } else if (definition instanceof Internal) {
+                               Internal def = (Internal)definition;
+                               return getURI(resourceCount, identities, def.parent) + "/" + def.name;
+                       } else {
+                               return "";
+                       }
+               }
+               return "<internal reference " + id + ">:";
+       }
+
 }
index 376ab173e1e9a9c5afaaa0058ee2c7a4b57f40ed..78c58e63dc698f82934dde034b9b21198a19d3d2 100644 (file)
Binary files a/bundles/org.simantics.help.ontology/graph.tg and b/bundles/org.simantics.help.ontology/graph.tg differ
index 73df6dc618bbb99e84f3638f8dbff795ea80bc28..1c45a220fcf005ac80bf0e2b92f9c988127987fc 100644 (file)
@@ -15,9 +15,10 @@ public class HistorySampler {
     public synchronized static TDoubleArrayList sample( HistorySamplerItem item, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {
 
        try {
-               item.open();
+               // If there is something pending at this point, flush before opening for read
                if(item.collector != null)
                        item.collector.flush();
+               item.open();
                return sample(item.iter, from, end, timeWindow, timeStep, resample);
        } finally {
                item.close();
@@ -25,10 +26,18 @@ public class HistorySampler {
     }
 
     public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {
+       return sample(iter, from, end, timeWindow, timeStep, resample, 0.0);
+    }
+
+    public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample, Double sampleFrom ) throws HistoryException, IOException {
 
        ExportInterpolation numberInterpolation = ExportInterpolation.LINEAR_INTERPOLATION;
 
-       double startTime = 0.0;
+       double startTime = from;
+       if(sampleFrom != null) {
+                // This option can be used do define the offset of sampling. Samples will be sampleFrom + n * timeStep
+               startTime = sampleFrom;
+       }
 
        TDoubleArrayList result = new TDoubleArrayList();
 
index 9173101eee8d77e57f218791d551ac9d2e5f6ff5..d2120cd78345d7fdccfcc7dcbb76d7e6d125c914 100644 (file)
@@ -1,11 +1,13 @@
 package org.simantics.issues.common;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.utils.ListUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
@@ -77,9 +79,20 @@ public class All {
        }
     }
 
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> [Resource]")
-    public static List<Resource> standardIssueContexts(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
-        return IssueUtils.getContextsForProperty(graph, property);
+    @SCLValue(type = "ReadGraph -> Resource -> a -> [Resource]")
+    public static List<Resource> standardIssueContexts(ReadGraph graph, Resource converter, Object property) throws DatabaseException {
+        if (property instanceof Variable) {
+            return IssueUtils.getContextsForProperty(graph, (Variable) property);
+        } else if (property instanceof Resource) {
+            Resource issue = (Resource) property;
+            IssueResource ISSUE = IssueResource.getInstance(graph);
+            Resource list = graph.getPossibleObject(issue, ISSUE.Issue_HasContexts);
+            if(list != null)
+                return ListUtils.toList(graph, list);
+            else
+                return Collections.emptyList();
+        }
+        throw new IllegalArgumentException("Unsupported property type: " + property);
     }
 
 }
index b12db40eb5f15f257efd60db944f405b84c7e92a..c072a1509ea33d52a41a360843a67308acb38783 100644 (file)
Binary files a/bundles/org.simantics.layer0/graph.tg and b/bundles/org.simantics.layer0/graph.tg differ
index 41f13c301b227fa2400d36bd65b9aa100a64017e..482f606fcb77d838e8a5ae4067e209bfc6d1d691 100644 (file)
@@ -107,7 +107,8 @@ L0.Ontology <T L0.Library <T L0.IndexRoot
     >-- L0.Ontology.global <R L0.HasProperty : L0.FunctionalRelation
         L0.HasLabel "Global?"
         --> L0.Boolean
-        
+    >-- L0.Ontology.download --> L0.String <R L0.HasProperty : L0.FunctionalRelation
+            
 L0.SharedOntology <T L0.Ontology
     >-- L0.SharedOntology.treatAsSystemOntology --> L0.Boolean <R L0.HasProperty : L0.FunctionalRelation
     @L0.assert L0.SharedOntology.treatAsSystemOntology false
@@ -123,4 +124,6 @@ L0.ResourceIdArray <T L0.Literal
 L0.PGraph <T L0.Entity
     >-- L0.PGraph.definition --> L0.String <R L0.HasProperty : L0.TotalFunction
     @L0.assert L0.PGraph.definition ""
+    
+L0.ExternalEntity <T L0.Entity    
  
\ No newline at end of file
index af7599ceead54c0ab64f6b3c9a55b5539e344b29..30e3885f439f2e971bcf5fc2dcbe53738e844b01 100644 (file)
@@ -53,7 +53,9 @@ L0.Functions.clusterValidator : L0.Function
 
 L0.SCLModule <T L0.Entity
     >-- L0.SCLModule.definition --> L0.String <R L0.HasProperty : L0.TotalFunction
+    >-- L0.SCLModule.alias --> L0.String <R L0.HasProperty : L0.TotalFunction
     @L0.assert L0.SCLModule.definition ""
+    @L0.assert L0.SCLModule.alias ""
 
 L0.entityReplacer ==> "Resource -> Resource -> <WriteGraph> ()" <R L0.HasProperty : L0.FunctionalRelation
     L0.HasDescription """Used for defining an SCL function that knows how to copy the contents from one entity instance to another when both instances are known to be of the same type.
index a4969326376554104f49639d034570dbefa92f60..2ea58b89cf78b46fab593e6a15df777c029d694a 100644 (file)
@@ -64,6 +64,7 @@ public class Layer0 {
     public final Resource Entity_published;
     public final Resource Entity_published_Inverse;
     public final Resource Enumeration;
+    public final Resource ExternalEntity;
     public final Resource ExternalValue;
     public final Resource False;
     public final Resource Final;
@@ -192,6 +193,8 @@ public class Layer0 {
     public final Resource NamespaceMigrationStep_Prefix_to;
     public final Resource NamespaceMigrationStep_Prefix_to_Inverse;
     public final Resource Ontology;
+    public final Resource Ontology_download;
+    public final Resource Ontology_download_Inverse;
     public final Resource Ontology_global;
     public final Resource Ontology_global_Inverse;
     public final Resource OrderedSet;
@@ -220,6 +223,8 @@ public class Layer0 {
     public final Resource SCLMigrationStep;
     public final Resource SCLMigrationStep_SCLMigrationStepAction;
     public final Resource SCLModule;
+    public final Resource SCLModule_alias;
+    public final Resource SCLModule_alias_Inverse;
     public final Resource SCLModule_definition;
     public final Resource SCLModule_definition_Inverse;
     public final Resource SCLValue;
@@ -352,6 +357,7 @@ public class Layer0 {
         public static final String Entity_published = "http://www.simantics.org/Layer0-1.1/Entity/published";
         public static final String Entity_published_Inverse = "http://www.simantics.org/Layer0-1.1/Entity/published/Inverse";
         public static final String Enumeration = "http://www.simantics.org/Layer0-1.1/Enumeration";
+        public static final String ExternalEntity = "http://www.simantics.org/Layer0-1.1/ExternalEntity";
         public static final String ExternalValue = "http://www.simantics.org/Layer0-1.1/ExternalValue";
         public static final String False = "http://www.simantics.org/Layer0-1.1/False";
         public static final String Final = "http://www.simantics.org/Layer0-1.1/Final";
@@ -480,6 +486,8 @@ public class Layer0 {
         public static final String NamespaceMigrationStep_Prefix_to = "http://www.simantics.org/Layer0-1.1/NamespaceMigrationStep/Prefix/to";
         public static final String NamespaceMigrationStep_Prefix_to_Inverse = "http://www.simantics.org/Layer0-1.1/NamespaceMigrationStep/Prefix/to/Inverse";
         public static final String Ontology = "http://www.simantics.org/Layer0-1.1/Ontology";
+        public static final String Ontology_download = "http://www.simantics.org/Layer0-1.1/Ontology/download";
+        public static final String Ontology_download_Inverse = "http://www.simantics.org/Layer0-1.1/Ontology/download/Inverse";
         public static final String Ontology_global = "http://www.simantics.org/Layer0-1.1/Ontology/global";
         public static final String Ontology_global_Inverse = "http://www.simantics.org/Layer0-1.1/Ontology/global/Inverse";
         public static final String OrderedSet = "http://www.simantics.org/Layer0-1.1/OrderedSet";
@@ -508,6 +516,8 @@ public class Layer0 {
         public static final String SCLMigrationStep = "http://www.simantics.org/Layer0-1.1/SCLMigrationStep";
         public static final String SCLMigrationStep_SCLMigrationStepAction = "http://www.simantics.org/Layer0-1.1/SCLMigrationStep/SCLMigrationStepAction";
         public static final String SCLModule = "http://www.simantics.org/Layer0-1.1/SCLModule";
+        public static final String SCLModule_alias = "http://www.simantics.org/Layer0-1.1/SCLModule/alias";
+        public static final String SCLModule_alias_Inverse = "http://www.simantics.org/Layer0-1.1/SCLModule/alias/Inverse";
         public static final String SCLModule_definition = "http://www.simantics.org/Layer0-1.1/SCLModule/definition";
         public static final String SCLModule_definition_Inverse = "http://www.simantics.org/Layer0-1.1/SCLModule/definition/Inverse";
         public static final String SCLValue = "http://www.simantics.org/Layer0-1.1/SCLValue";
@@ -650,6 +660,7 @@ public class Layer0 {
         Entity_published = getResourceOrNull(graph, URIs.Entity_published);
         Entity_published_Inverse = getResourceOrNull(graph, URIs.Entity_published_Inverse);
         Enumeration = getResourceOrNull(graph, URIs.Enumeration);
+        ExternalEntity = getResourceOrNull(graph, URIs.ExternalEntity);
         ExternalValue = getResourceOrNull(graph, URIs.ExternalValue);
         False = getResourceOrNull(graph, URIs.False);
         Final = getResourceOrNull(graph, URIs.Final);
@@ -778,6 +789,8 @@ public class Layer0 {
         NamespaceMigrationStep_Prefix_to = getResourceOrNull(graph, URIs.NamespaceMigrationStep_Prefix_to);
         NamespaceMigrationStep_Prefix_to_Inverse = getResourceOrNull(graph, URIs.NamespaceMigrationStep_Prefix_to_Inverse);
         Ontology = getResourceOrNull(graph, URIs.Ontology);
+        Ontology_download = getResourceOrNull(graph, URIs.Ontology_download);
+        Ontology_download_Inverse = getResourceOrNull(graph, URIs.Ontology_download_Inverse);
         Ontology_global = getResourceOrNull(graph, URIs.Ontology_global);
         Ontology_global_Inverse = getResourceOrNull(graph, URIs.Ontology_global_Inverse);
         OrderedSet = getResourceOrNull(graph, URIs.OrderedSet);
@@ -806,6 +819,8 @@ public class Layer0 {
         SCLMigrationStep = getResourceOrNull(graph, URIs.SCLMigrationStep);
         SCLMigrationStep_SCLMigrationStepAction = getResourceOrNull(graph, URIs.SCLMigrationStep_SCLMigrationStepAction);
         SCLModule = getResourceOrNull(graph, URIs.SCLModule);
+        SCLModule_alias = getResourceOrNull(graph, URIs.SCLModule_alias);
+        SCLModule_alias_Inverse = getResourceOrNull(graph, URIs.SCLModule_alias_Inverse);
         SCLModule_definition = getResourceOrNull(graph, URIs.SCLModule_definition);
         SCLModule_definition_Inverse = getResourceOrNull(graph, URIs.SCLModule_definition_Inverse);
         SCLValue = getResourceOrNull(graph, URIs.SCLValue);
index be90b1512889172f08f69ad4292a8844da3ea142..0ac20b8f448112534d33dc0f7fd3536aacec62c6 100644 (file)
Binary files a/bundles/org.simantics.modeling.ontology/graph.tg and b/bundles/org.simantics.modeling.ontology/graph.tg differ
index 3f33c47fc49c75ffba2827e11e77b1210f3d89f6..ebc49fbe09ccdf7357592909ab355980c418333f 100644 (file)
@@ -325,6 +325,15 @@ MOD.scl : L0.Template
               L0.SCLValue.expression %expression
               L0.HasValueType %valueType
 
+MOD.sclAssertion : L0.Template
+    @template %type %property %expression %valueType
+        %type
+            L0.Asserts _ : L0.Assertion
+              L0.HasPredicate %property
+              L0.HasObject _ : MOD.SCLValue
+                L0.SCLValue.expression %expression
+                L0.HasValueType %valueType
+
 MOD.Functions.obtainedString : L0.Function
   L0.HasValueType "String"
 
index fa0f29cba7b59f295e159eabcb093c9f4ad5ceea..c838c0a3648850a5fbb0793844e664577cd4fc07 100644 (file)
@@ -636,6 +636,9 @@ ACTIONS.CompilePGraphs : ACT.Action
 ACTIONS.RenameDiagramComponents : ACT.Action
 ACTIONS.Help : ACT.Action
 
+ACTIONS.NavigateToSubstructure
+  @MOD.sclAction "navigateToSubstructureAction"
+
 ACTIONS.NewProceduralComponentType : ACT.Action
 ACTIONS.NewComponentType : ACT.Action
 
index ee0f501252c4fa39b6e66ef6ae5ea631b79a2a08..8504813e88353db3452e3f009dd805e9530001ca 100644 (file)
@@ -259,6 +259,7 @@ public class ModelingResources {
     public final Resource ModelingActionContext_Actions_Lock;
     public final Resource ModelingActionContext_Actions_MergeFlags;
     public final Resource ModelingActionContext_Actions_MigrateComponentType;
+    public final Resource ModelingActionContext_Actions_NavigateToSubstructure;
     public final Resource ModelingActionContext_Actions_NewComponentType;
     public final Resource ModelingActionContext_Actions_NewConnectionPoint;
     public final Resource ModelingActionContext_Actions_NewDocument;
@@ -428,6 +429,7 @@ public class ModelingResources {
     public final Resource editorContribution;
     public final Resource scl;
     public final Resource sclAction;
+    public final Resource sclAssertion;
     public final Resource sclTest;
     public final Resource self;
     public final Resource self_Inverse;
@@ -684,6 +686,7 @@ public class ModelingResources {
         public static final String ModelingActionContext_Actions_Lock = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/Lock";
         public static final String ModelingActionContext_Actions_MergeFlags = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/MergeFlags";
         public static final String ModelingActionContext_Actions_MigrateComponentType = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/MigrateComponentType";
+        public static final String ModelingActionContext_Actions_NavigateToSubstructure = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/NavigateToSubstructure";
         public static final String ModelingActionContext_Actions_NewComponentType = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/NewComponentType";
         public static final String ModelingActionContext_Actions_NewConnectionPoint = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/NewConnectionPoint";
         public static final String ModelingActionContext_Actions_NewDocument = "http://www.simantics.org/Modeling-1.2/ModelingActionContext/Actions/NewDocument";
@@ -853,6 +856,7 @@ public class ModelingResources {
         public static final String editorContribution = "http://www.simantics.org/Modeling-1.2/editorContribution";
         public static final String scl = "http://www.simantics.org/Modeling-1.2/scl";
         public static final String sclAction = "http://www.simantics.org/Modeling-1.2/sclAction";
+        public static final String sclAssertion = "http://www.simantics.org/Modeling-1.2/sclAssertion";
         public static final String sclTest = "http://www.simantics.org/Modeling-1.2/sclTest";
         public static final String self = "http://www.simantics.org/Modeling-1.2/self";
         public static final String self_Inverse = "http://www.simantics.org/Modeling-1.2/self/Inverse";
@@ -1119,6 +1123,7 @@ public class ModelingResources {
         ModelingActionContext_Actions_Lock = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_Lock);
         ModelingActionContext_Actions_MergeFlags = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_MergeFlags);
         ModelingActionContext_Actions_MigrateComponentType = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_MigrateComponentType);
+        ModelingActionContext_Actions_NavigateToSubstructure = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_NavigateToSubstructure);
         ModelingActionContext_Actions_NewComponentType = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_NewComponentType);
         ModelingActionContext_Actions_NewConnectionPoint = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_NewConnectionPoint);
         ModelingActionContext_Actions_NewDocument = getResourceOrNull(graph, URIs.ModelingActionContext_Actions_NewDocument);
@@ -1288,6 +1293,7 @@ public class ModelingResources {
         editorContribution = getResourceOrNull(graph, URIs.editorContribution);
         scl = getResourceOrNull(graph, URIs.scl);
         sclAction = getResourceOrNull(graph, URIs.sclAction);
+        sclAssertion = getResourceOrNull(graph, URIs.sclAssertion);
         sclTest = getResourceOrNull(graph, URIs.sclTest);
         self = getResourceOrNull(graph, URIs.self);
         self_Inverse = getResourceOrNull(graph, URIs.self_Inverse);
index 34b4f82f27767631e6b108b949affa7a0639abb8..7550f707321dfaadbd5d3328628edf66394a408e 100644 (file)
@@ -114,14 +114,14 @@ importJava "org.simantics.modeling.ModelingUtils" where
 
 setMonitorPropertyValue :: Monitor -> String -> String -> <WriteGraph> ()
 setMonitorPropertyValue monitor property newValue = do
-    monitorUri = uriOf (toResource monitor)
+    monitorUri = uriOf monitor
     completeUri = monitorUri + "#" + property + "#HasDisplayValue"
     propertyVariable = variable completeUri
     setValue propertyVariable newValue
     
 setFlagTablePropertyValue :: FlagTable -> String -> String -> <WriteGraph> ()
 setFlagTablePropertyValue flagTable property newValue = do
-    flagTableUri = uriOf (toResource flagTable)
+    flagTableUri = uriOf flagTable
     completeUri = flagTableUri + "#" + property + "#HasDisplayValue"
     propertyVariable = variable completeUri
     setValue propertyVariable newValue
index f396a58152a00e9d00747388ce43d407398832ed..525c8da5244abc27f19951b450c52d5136266dc0 100644 (file)
@@ -13,7 +13,7 @@ Require-Bundle: org.simantics.project;bundle-version="1.0.0",
  org.simantics.modeling;bundle-version="1.0.0";visibility:=reexport,
  org.simantics.utils.thread.swt;bundle-version="1.0.0",
  org.simantics.simulation;bundle-version="1.0.0",
javax.vecmath;bundle-version="1.5.2",
org.apache.commons.math3;bundle-version="3.6.1",
  org.simantics.browsing.ui.platform;bundle-version="1.0.0";visibility:=reexport,
  org.simantics.structural.ui;bundle-version="1.0.0",
  org.eclipse.ui.forms;bundle-version="3.4.1",
@@ -62,7 +62,8 @@ Require-Bundle: org.simantics.project;bundle-version="1.0.0",
  org.simantics.silk.ontology;bundle-version="1.1.0",
  org.simantics.image.ui;bundle-version="1.0.0",
  org.simantics.export.core;bundle-version="1.0.0",
- org.slf4j.api
+ org.slf4j.api,
+ org.simantics.graphfile.ontology
 Export-Package: org.simantics.modeling.ui,
  org.simantics.modeling.ui.actions,
  org.simantics.modeling.ui.chart.property,
index 8277568556964818b6d518229d1eebc4dd381f0a..ee4d7885eac17b4831623d858bbc56afde879262 100644 (file)
@@ -21,11 +21,11 @@ importJava "org.simantics.modeling.ui.SCLLibrary" where
     getLibrary :: Model -> String -> <ReadGraph> Library
     
 librariesOf :: Model -> <ReadGraph> [Library]
-librariesOf model = recurse L0.Library (toResource model)
+librariesOf model = recurse L0.Library model
   where
     recurse t r = do
-        cs = resourceChildrenOf r 
-        libraries = map fromResource $ filter isLibrary cs
+        cs = children r 
+        libraries = filter isLibrary cs
         libraryGrp = filter (not . isLibrary) cs
         libraries + concatMap (recurse t) libraryGrp
     isLibrary r = isInstanceOf r L0.Library
\ No newline at end of file
index ecacf009097034cbc6dd9c43bdc40d4df0aa5a00..b821fcc03f10b5105ff5de01d4ce45dd3aed102a 100644 (file)
@@ -123,7 +123,9 @@ printActionDetails action = do
 @private
 decorateLabelStub :: LabelDecorator -> String -> String -> <Proc> ()
 decorateLabelStub decorator key value = do
-    fontti = decorateFont decorator getDefaultFontDescriptor key 0
+    fontti = match decorateFont decorator (Just getDefaultFontDescriptor) key 0 with
+      Nothing -> ""
+      Just font -> ""
     fontti = decorateBackground decorator Nothing key 0
     fontti = decorateForeground decorator Nothing key 0
     laabeli = decorateLabel decorator value key 0
index a4b06495a4b6f155b1a4abd73170e960e1e1cde1..d3890192e711495363cff0b7ac6517cdc191f8f1 100644 (file)
@@ -96,7 +96,7 @@ importJava "org.simantics.browsing.ui.content.LabelDecorator" where
     decorateLabel :: LabelDecorator -> String -> String -> Integer -> <Proc> String
     decorateForeground :: LabelDecorator -> a -> String -> Integer -> <Proc> a
     decorateBackground :: LabelDecorator -> a -> String -> Integer -> <Proc> a
-    decorateFont :: LabelDecorator -> a -> String -> Integer -> <Proc> a
+    decorateFont :: LabelDecorator -> Maybe a -> String -> Integer -> <Proc> Maybe a
 
 importJava "org.simantics.browsing.ui.CheckedState" where
     data CheckedState
@@ -105,7 +105,8 @@ importJava "org.simantics.browsing.ui.content.Labeler$Modifier" where
     data Modifier
     
     getValue :: Modifier -> <Proc> String
-    isValid :: Modifier -> String -> <Proc> String
+    isValid :: Modifier -> String -> <Proc> Maybe String
+    modify :: Modifier -> String -> <Proc> ()
 
 importJava "org.simantics.browsing.ui.model.browsecontexts.BrowseContexts" where
     toBrowseContextG :: Vector String -> <ReadGraph> BrowseContext
@@ -118,3 +119,6 @@ createBrowseContext :: [Resource] -> <ReadGraph> BrowseContext
 createBrowseContext resource = do
     create resource
 
+importJava "org.simantics.browsing.ui.common.NodeContextBuilder" where
+    buildWithInput :: a -> <Proc> NodeContext
+
index c13f3cb430f8bdefd525c93f9b3329338a61308a..4272b9de7f28e9277c94c29328c7546afdcbddf6 100644 (file)
@@ -35,6 +35,7 @@ import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.IndexRoot;
 import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.request.UniqueRead;
@@ -58,6 +59,7 @@ import org.simantics.db.layer0.util.SimanticsKeys;
 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
 import org.simantics.db.service.SerialisationSupport;
 import org.simantics.graph.compiler.CompilationResult;
+import org.simantics.graph.compiler.ExternalFileLoader;
 import org.simantics.graph.compiler.GraphCompiler;
 import org.simantics.graph.compiler.GraphCompilerPreferences;
 import org.simantics.graph.compiler.ValidationMode;
@@ -68,6 +70,7 @@ import org.simantics.graph.diff.TransferableGraphDelta1;
 import org.simantics.graph.representation.Identity;
 import org.simantics.graph.representation.Root;
 import org.simantics.graph.representation.TransferableGraph1;
+import org.simantics.graphfile.ontology.GraphFileResource;
 import org.simantics.layer0.Layer0;
 import org.simantics.ltk.ISource;
 import org.simantics.ltk.Problem;
@@ -270,7 +273,33 @@ public class CompilePGraphs implements ActionFactory {
                                prefs.validate = true;
                                prefs.validateRelationRestrictions = ValidationMode.ERROR;
                                prefs.validateResourceHasType = ValidationMode.IGNORE;
-                               final CompilationResult result = GraphCompiler.compile("1.1", sources, dependencies, null, prefs);
+                               
+                               final CompilationResult result = Simantics.sync(new UniqueRead<CompilationResult>() {
+
+                                               @Override
+                                               public CompilationResult perform(ReadGraph graph) throws DatabaseException {
+                                                       
+                                                       final Resource root = graph.syncRequest(new IndexRoot(r));
+                                                       final String baseURI = graph.getURI(root);
+
+                                                       ExternalFileLoader fileLoader = new ExternalFileLoader() {
+                                                               @Override
+                                                               public byte[] load(String fileName) throws IOException {
+                                                                       try {
+                                                                               GraphFileResource GF = GraphFileResource.getInstance(graph);
+                                                                               Resource file = graph.getResource(baseURI + "/" + fileName);
+                                                                               return graph.getRelatedValue(file, GF.HasFiledata, Bindings.BYTE_ARRAY);
+                                                                       } catch (DatabaseException e) {
+                                                                               throw new IOException(e);
+                                                                       }
+                                                               }
+                                                       };
+
+                                                       return GraphCompiler.compile("1.1", sources, dependencies, fileLoader, prefs);
+                                                       
+                                               }
+                                       
+                               });
                                
                                for(Problem problem : result.getErrors())
                                        errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n");
index 41062fef81798496ee4569d218240e1811867df8..478d8b761046177484db3ecbc02643ada1801feb 100644 (file)
@@ -115,17 +115,18 @@ public class ModeledActions extends DynamicMenuContribution implements IExecutab
         for (Object o : selection) {
             if ((o instanceof IAdaptable)) {
                    NodeContext nodeContext = ((IAdaptable) o).getAdapter(NodeContext.class);
-                   if (nodeContext != null)
+                   if (nodeContext != null) {
                        result.add(nodeContext);
-            } else if (o instanceof WorkbenchSelectionElement) {
-               try {
-                                       Resource res = WorkbenchSelectionUtils.getPossibleResource((WorkbenchSelectionElement)o);
-                                       if(res != null) {
-                                               result.add(NodeContextBuilder.buildWithInput(res));
-                                       }
-                               } catch (DatabaseException e) {
-                                   LOGGER.error("Failed to get node contexts for selection.", e);
-                               }
+                       continue;
+                   }
+            }
+            try {
+               Resource res = WorkbenchSelectionUtils.getPossibleResource(o);
+               if(res != null) {
+                       result.add(NodeContextBuilder.buildWithInput(res));
+               }
+            } catch (DatabaseException e) {
+               LOGGER.error("Failed to get node contexts for selection.", e);
             }
         }
 
index 921ee62999a7f3382849c34dfb91c379fd0f0c49..9c9ebfe9e95b90c1f1dcd6e6effa8965e485838d 100644 (file)
@@ -72,7 +72,7 @@ public class SymbolCodeDocumentProvider2 extends SCLModuleEditorDocumentProvider
                errorHappened = false;
                return graph.getRelatedValue(text, L0.SCLValue_expression, Bindings.STRING);
        }
-       throw new DatabaseException("No symbol code was defined.");
+       return "";
     }
 
     protected void updateAnnotations() {
index 7394ef410604ef3bcbbb43115f30345971deaa66..48c258d4737ec0c26aeb153b0b1d1bfc92795f3a 100644 (file)
@@ -72,7 +72,7 @@ public class SymbolDropHandlerDocumentProvider extends SCLModuleEditorDocumentPr
                errorHappened = false;
                return graph.getRelatedValue(text, L0.SCLValue_expression, Bindings.STRING);
        }
-       throw new DatabaseException("No symbol code was defined.");
+       return "";
     }
 
     protected void updateAnnotations() {
index 03edf6577963485a998a01c5b8409847b1beecca..60f28f17b9efa222bb9e6320c09586a51451fe30 100644 (file)
@@ -22,8 +22,8 @@ import java.util.Collection;
 import java.util.EnumSet;
 
 import javax.swing.JSlider;
-import javax.vecmath.Vector2d;
 
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.element.ElementClass;
 import org.simantics.g2d.element.ElementHints;
@@ -383,11 +383,9 @@ public class SliderClass {
             return Double.NaN;
         double angrad = Math.toRadians(angle);
 
-        Vector2d forcedAxis = new Vector2d(Math.cos(angrad), Math.sin(angrad));
-        Vector2d x = new Vector2d(tr.getScaleX(), tr.getShearX());
-        forcedAxis.normalize();
-        x.normalize();
-        double cosa = forcedAxis.dot(x);
+        Vector2D forcedAxis = new Vector2D(Math.cos(angrad), Math.sin(angrad));
+        Vector2D x = new Vector2D(tr.getScaleX(), tr.getShearX()).normalize();
+        double cosa = forcedAxis.dotProduct(x);
         double delta = Math.acos(cosa);
         return delta;
     }
diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/ConnectionPointNameStyle.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/ConnectionPointNameStyle.java
new file mode 100644 (file)
index 0000000..a4f32e8
--- /dev/null
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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 - #7107 original implementation
+ *     Semantum Oy - #7107 adaptation for general use
+ *******************************************************************************/
+package org.simantics.modeling.ui.diagram.style;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.primitiverequest.OrderedSet;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.diagram.adapter.RouteGraphUtils;
+import org.simantics.diagram.connection.RouteGraphConnectionClass;
+import org.simantics.diagram.connection.RouteTerminal;
+import org.simantics.diagram.elements.TextNode;
+import org.simantics.diagram.profile.StyleBase;
+import org.simantics.diagram.synchronization.graph.BasicResources;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.g2d.utils.Alignment;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.profile.EvaluationContext;
+import org.simantics.scenegraph.profile.common.ProfileVariables;
+import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.utils.datastructures.map.Tuple;
+
+/**
+ * @author Teemu Mätäsniemi
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class ConnectionPointNameStyle extends StyleBase<List<ConnectionPointNameStyle.Result>> {
+
+    protected static class Result extends Tuple {
+        public Result(String string, AffineTransform tr, Integer direction) {
+            super(string, tr, direction);
+        }
+        public String getString() {
+            return (String) getField(0);
+        }
+        public AffineTransform getTransform() {
+            return (AffineTransform) getField(1);
+        }
+        public Integer getAllowedDirections() {
+            return (Integer) getField(2);
+        }
+    }
+
+    protected static final String PARENT_NODE_NAME_PREFIX = "_tNames";
+    protected static final String NODE_NAME_PREFIX        = "_";
+
+    protected static final Font   FONT = Font.decode("Arial 6");
+
+    protected static final double DEFAULT_SCALE = 0.05;
+
+    private Color backgroundColor = Color.WHITE;
+    private Color textColor = Color.BLACK;
+
+    private double textScale;
+
+    public ConnectionPointNameStyle() {
+        this(DEFAULT_SCALE);
+    }
+
+    public ConnectionPointNameStyle(double textScale) {
+        this.textScale = textScale;
+    }
+
+    @Override
+    public List<Result> calculateStyle(
+            ReadGraph graph,
+            Resource runtimeDiagram,
+            Resource entry,
+            Resource element,
+            Variable configuration)
+                    throws DatabaseException
+    {
+        BasicResources BR = BasicResources.getInstance(graph);
+        Layer0 L0 = BR.L0;
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+
+        Resource comp = graph.getPossibleObject(element, MOD.ElementToComponent);
+        if (comp == null)
+            return Collections.emptyList();
+        String compName = graph.getPossibleRelatedValue(comp, L0.HasName, Bindings.STRING);
+        if (compName == null)
+            return Collections.emptyList();
+
+        // Only process defined elements since those can contain terminal definitions
+        Resource elementType = graph.getPossibleType(element, BR.DIA.DefinedElement);
+        if (elementType == null)
+            return Collections.emptyList();
+
+        // Need parent information to calculate absolute positions of terminals
+        // and to make the result unique for instances of the same symbol.
+        AffineTransform parentTransform = DiagramGraphUtil.getAffineTransform(graph, element);
+        List<Result> result = new ArrayList<>();
+        result.add(new Result(compName, parentTransform, null));
+
+        Resource orderedSet = graph.getPossibleObject(elementType, BR.STR.IsDefinedBy);
+        if (orderedSet != null) {
+            for (Resource el : graph.syncRequest(new OrderedSet(orderedSet))) {
+                Resource gcp = graph.getPossibleObject(el, BR.DIA.HasConnectionPoint);
+                if (gcp != null) {
+                    Resource cpRel = graph.getPossibleObject(gcp, MOD.DiagramConnectionRelationToConnectionRelation);
+                    if (cpRel == null)
+                        continue;
+                    String name = graph.getPossibleRelatedValue(cpRel, L0.HasName, Bindings.STRING);
+                    if (name != null) {
+                        Integer allowedDirections = graph.getPossibleRelatedValue(el, BR.DIA.Terminal_AllowedDirections, Bindings.INTEGER);
+                        result.add(new Result(name, DiagramGraphUtil.getAffineTransform(graph, el), allowedDirections));
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    protected static AffineTransform translateAndScaleIfNeeded(AffineTransform tr, double rotation, double offsetX, double offsetY, double scale) {
+        if (rotation != 0 || offsetX != 0.0 || offsetY != 0.0 || scale != 1.0) {
+            tr = new AffineTransform(tr);
+            if (rotation != 0)
+                tr.rotate(rotation);
+            if (offsetX != 0 || offsetY != 0)
+                tr.translate(offsetX, offsetY);
+            if (scale != 1.0)
+                tr.scale(scale, scale);
+        }
+        return tr;
+    }
+
+    protected AffineTransform getTerminalTransform(AffineTransform transform, double rotation, double offsetX, double offsetY, double scale) {
+        return translateAndScaleIfNeeded(transform, rotation, offsetX, offsetY, scale);
+    }
+
+    @Override
+    public void applyStyleForNode(EvaluationContext observer, INode _node, List<Result> resultList) {
+        // always clean up old items before drawing new items
+        cleanupStyleForNode(_node);
+
+        int count = resultList.size();
+        if (resultList == null || count < 2)
+            return;
+
+        G2DParentNode parentNode = ProfileVariables.claimChild(_node, "", PARENT_NODE_NAME_PREFIX, G2DParentNode.class, observer);
+        parentNode.setTransform(resultList.get(0).getTransform());
+        parentNode.setZIndex(Integer.MAX_VALUE >> 1);
+
+        Rectangle2D eBounds = NodeUtil.getLocalElementBounds(_node);
+
+        for (int i = 1; i < count; ++i) {
+            Result result = resultList.get(i);
+            TextNode node = ProfileVariables.claimChild(parentNode, "", NODE_NAME_PREFIX + i, TextNode.class, observer);
+            node.setZIndex(i);
+            node.setBackgroundColor(backgroundColor);
+            node.setColor(textColor);
+            node.setText(result.getString());
+            node.setVerticalAlignment((byte) Alignment.CENTER.ordinal());
+            node.setAutomaticTextFlipping(TextNode.TextFlipping.VerticalTextDownwards);
+
+            Alignment hAlign = Alignment.LEADING;
+            AffineTransform tr = result.getTransform();
+            double trX = tr.getTranslateX(),
+                   trY = tr.getTranslateY();
+            double dx = 0, dy = 0, r = 0;
+            double ts = 0.6;
+
+            Integer dir = result.getAllowedDirections();
+            int directions = dir != null
+                    ? RouteGraphUtils.rotateDirection(dir, tr)
+                    : RouteGraphConnectionClass.shortestDirectionOutOfBounds(trX, trY, eBounds);
+
+            //System.out.format("%24s: DIR %d (%s)%n", result.getString(), directions, tr.toString());
+
+            if (trX == 0 && trY == 0) {
+                hAlign = Alignment.CENTER;
+            } else {
+                boolean up = (directions & RouteTerminal.DIR_UP) != 0;
+                boolean down = (directions & RouteTerminal.DIR_DOWN) != 0;
+                boolean left = (directions & RouteTerminal.DIR_LEFT) != 0;
+                boolean right = (directions & RouteTerminal.DIR_RIGHT) != 0;
+
+                double ldx = Math.abs(eBounds.getMinX() - trX);
+                double rdx = Math.abs(eBounds.getMaxX() - trX);
+                double tdy = Math.abs(eBounds.getMinY() - trY);
+                double bdy = Math.abs(eBounds.getMaxY() - trY);
+
+                if (left && ldx <= rdx && ldx <= tdy && ldx <= bdy) {
+                    dx = -ts;
+                    hAlign = Alignment.TRAILING;
+                } else if (right && rdx <= ldx && rdx <= tdy && rdx <= bdy) {
+                    dx = ts;
+                    hAlign = Alignment.LEADING;
+                } else if (up && tdy <= ldx && tdy <= rdx && tdy <= bdy) {
+                    dx = -ts;
+                    r = Math.PI/2;
+                    hAlign = Alignment.TRAILING;
+                } else if (down && bdy <= ldx && bdy <= rdx && bdy <= tdy) {
+                    dx = ts;
+                    r = Math.PI/2;
+                    hAlign = Alignment.LEADING;
+                }
+            }
+
+            node.setHorizontalAlignment((byte) hAlign.ordinal());
+            node.setTransform(getTerminalTransform(tr, r, dx, dy, textScale));
+        }
+    }
+
+    @Override
+    protected void cleanupStyleForNode(INode node) {
+        if (node instanceof SingleElementNode) {
+            ProfileVariables.denyChild(node, "", PARENT_NODE_NAME_PREFIX);
+        }
+    }
+
+}
index df01fe5d267207d55881afff88007f6273545df3..9a1ea8360a751fe67aa294523be125f10a3f5150 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 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
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - #7116 regression fix
  *******************************************************************************/
 package org.simantics.modeling.ui.modelBrowser.handlers;
 
@@ -21,61 +22,71 @@ import org.simantics.Simantics;
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
-import org.simantics.db.common.request.ResourceRead;
-import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.modeling.ModelingResources;
 import org.simantics.modeling.PropertyVariables;
 import org.simantics.ui.selection.WorkbenchSelectionUtils;
 import org.simantics.utils.ui.AdaptionUtils;
+import org.slf4j.LoggerFactory;
 
 public class ContextualHelp extends AbstractHandler {
 
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ContextualHelp.class);
+
     private static String getPossibleId(ExecutionEvent event) {
-        String id = null;
         try {
-            Resource element = WorkbenchSelectionUtils.getPossibleResource(event);
-            id = Simantics.getSession().syncRequest(new ResourceRead<String>(element) {
+            ISelection sel = HandlerUtil.getCurrentSelection(event);
+            Resource resource = WorkbenchSelectionUtils.getPossibleResource(sel);
+            Variable variable = WorkbenchSelectionUtils.getPossibleVariable(sel);
+            if (sel.isEmpty() && resource == null && variable == null)
+                return null;
 
+            return Simantics.getSession().syncRequest(new UniqueRead<String>() {
                 @Override
                 public String perform(ReadGraph graph) throws DatabaseException {
                     ModelingResources MOD = ModelingResources.getInstance(graph);
-                    Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
-                    if (component != null)
-                        return graph.getPossibleRelatedValue2(component, MOD.contextualHelpId, Bindings.STRING);
+                    if (resource != null) {
+                        Resource component = graph.getPossibleObject(resource, MOD.ElementToComponent);
+                        String id = component != null ? graph.getPossibleRelatedValue2(component, MOD.contextualHelpId, Bindings.STRING) : null;
+                        if (id != null)
+                            return id;
+                        id = graph.getPossibleRelatedValue2(resource, MOD.contextualHelpId, Bindings.STRING);
+                        if (id != null)
+                            return id;
+                    }
 
-                    Variable var = WorkbenchSelectionUtils.getPossibleVariable(event);
-                    if (var != null)
-                        return var.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING);
+                    if (variable != null) {
+                        String id = variable.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING);
+                        if (id != null)
+                            return id;
+                    }
 
-                    ISelection sel = HandlerUtil.getCurrentSelection(event);
+                    // TODO: consider removing this block
                     if (sel != null) {
                         PropertyVariables vars = AdaptionUtils.adaptToSingle(sel, PropertyVariables.class);
-                        if (vars != null) {
-                            var = vars.getConfiguration();
-                            if (var != null)
-                                var.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING);
-                        }
+                        Variable var = vars != null ? vars.getConfiguration() : null;
+                        String id = var != null ? var.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING) : null;
+                        if (id != null)
+                            return id;
                     }
+
                     return null;
                 }
             });
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("", e);
+            return null;
         }
-        return id;
     }
 
     @Override
     public Object execute(ExecutionEvent event) throws ExecutionException {
-
         String id = getPossibleId(event);
         if (id != null)
             PlatformUI.getWorkbench().getHelpSystem().displayHelp(id);
-
         return null;
-
     }
 
 }
index dc0ee266bf92d3235e09a9471d426e37fc595ac0..952d9c8c4a057a62c6b431567b877b95e93ec6c8 100644 (file)
@@ -31,7 +31,7 @@ public class ConnectionRelationLabelDecorationRule implements LabelDecorationRul
     static LabelDecorator DECO = new LabelDecorator.Stub() {
         @SuppressWarnings("unchecked")
         public <F> F decorateFont(F font, String column, int itemIndex) {
-            return (F) ((FontDescriptor) font).withStyle(SWT.BOLD); 
+            return font != null ? (F) ((FontDescriptor) font).withStyle(SWT.BOLD) : null;
         }
     };
 
index e3101dce2e31ea8d2e200d9f96f56c692e6e463f..7f0559348d5b67d227512b37c433b5b407936041 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 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
@@ -8,14 +8,17 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - (#7084) refactoring, page numbering support
  *******************************************************************************/
 package org.simantics.modeling.ui.pdf;
 
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.Security;
 import java.util.Collection;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.eclipse.core.runtime.IProduct;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -27,9 +30,10 @@ import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.util.SessionGarbageCollection;
-import org.simantics.db.management.ISessionContext;
 import org.simantics.document.DocumentSettings;
 import org.simantics.document.DocumentUtils;
+import org.simantics.export.core.pdf.FontMapping;
+import org.simantics.export.core.pdf.PageNumbering;
 import org.simantics.export.core.pdf.ServiceBasedPdfExportPageEvent;
 import org.simantics.modeling.requests.CollectionRequest;
 import org.simantics.modeling.requests.CollectionResult;
@@ -39,29 +43,34 @@ import org.simantics.ui.jobs.SessionGarbageCollectorJob;
 import org.simantics.utils.page.PageDesc;
 import org.simantics.utils.page.PageOrientation;
 import org.simantics.utils.threads.WorkerThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.kitfox.svg.SVGCache;
 import com.lowagie.text.Document;
 import com.lowagie.text.DocumentException;
-import com.lowagie.text.FontFactory;
+import com.lowagie.text.ExceptionConverter;
 import com.lowagie.text.PageSize;
 import com.lowagie.text.Rectangle;
-import com.lowagie.text.pdf.DefaultFontMapper;
+import com.lowagie.text.pdf.FontMapper;
 import com.lowagie.text.pdf.PdfBoolean;
 import com.lowagie.text.pdf.PdfContentByte;
 import com.lowagie.text.pdf.PdfName;
 import com.lowagie.text.pdf.PdfTemplate;
 import com.lowagie.text.pdf.PdfWriter;
 
+/**
+ * @author Tuukka Lehtonen
+ */
 public class DiagramPrinter {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(DiagramPrinter.class);
+
     public static CollectionResult browse(IProgressMonitor monitor, RequestProcessor processor, Resource[] input) throws DatabaseException {
         final CollectionResult result = processor.syncRequest(new CollectionRequest(monitor, DiagramPreferenceUtil.getDefaultPreferences().getCompletePageDesc(), input));
         return result;
     }
 
-    private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();
-
     /**
      * @param monitor the progress monitor to use for reporting progress to the
      *        user. It is the caller's responsibility to call done() on the
@@ -76,38 +85,88 @@ public class DiagramPrinter {
      * @throws FileNotFoundException
      */
     public static void printToPdf(
-               IProgressMonitor monitor, 
-               PDFExportPlan exportPlan, 
-               String exportPath, 
-               Collection<Node> flattenedNodes,
-            ISessionContext sessionContext) 
-    throws PdfException {
-        Collection<Node> flattened = flattenedNodes;
+            IProgressMonitor monitor, 
+            PDFExportPlan exportPlan, 
+            String exportPath, 
+            Collection<Node> flattenedNodes) 
+                throws PdfException
+    {
+        if (!exportPlan.addPageNumbers) {
+            printToPdfWithoutPageNumbers(monitor, exportPlan, exportPath, flattenedNodes);
+        } else {
+            SubMonitor mon = SubMonitor.convert(monitor, "Export to PDF", flattenedNodes.size() * 3);
+
+            Path tempOutput = Paths.get(exportPath + ".tmp");
+            Path finalOutput = Paths.get(exportPath);
+
+            int exportedPages = printToPdfWithoutPageNumbers(
+                    mon.newChild(flattenedNodes.size() * 2, SubMonitor.SUPPRESS_NONE),
+                    exportPlan,
+                    tempOutput.toString(),
+                    flattenedNodes);
+
+            if (mon.isCanceled()) {
+                tempOutput.toFile().delete();
+                throw new OperationCanceledException();
+            }
 
-        SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattened.size() * 2);
+            try {
+                mon.setWorkRemaining(exportedPages);
+                mon.setTaskName("Numbering output pages");
+                mon.subTask("");
+                PageNumbering.addPageNumbers(
+                        mon.newChild(flattenedNodes.size()),
+                        tempOutput, finalOutput,
+                        exportPlan.pageNumberPosition,
+                        exportPlan.pageNumberFormat);
+            } catch (IOException | DocumentException | ExceptionConverter e) {
+                throw new PdfException(e);
+            } finally {
+                tempOutput.toFile().delete();
+            }
+        }
+    }
+
+    /**
+     * @param monitor the progress monitor to use for reporting progress to the
+     *        user. It is the caller's responsibility to call done() on the
+     *        given monitor. Accepts <code>null</code>, indicating that no
+     *        progress should be reported and that the operation cannot be
+     *        cancelled.
+     * 
+     * @param exportPath
+     * @param flattenedNodes
+     * @return number of pages printed
+     * @throws PdfException
+     * @since 1.28.0
+     */
+    public static int printToPdfWithoutPageNumbers(
+            IProgressMonitor monitor, 
+            PDFExportPlan exportPlan, 
+            String exportPath, 
+            Collection<Node> flattenedNodes) 
+                    throws PdfException
+    {
+        SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattenedNodes.size() * 2);
 
         WorkerThread workerThread = new WorkerThread("Diagram PDF Painter");
         workerThread.start();
 
         PdfWriter writer = null;
         Document document = null;
+        int exportedPages = 0;
 
         try {
             progress.subTask("Loading system fonts");
-            DefaultFontMapper mapper = new DefaultFontMapper();
-            if (fontFactoryInitialized.compareAndSet(false, true)) {
-                // Only register directories once.
-                FontFactory.registerDirectories();
-            }
+            FontMapper mapper = FontMapping.defaultFontMapper();
 
             SessionGarbageCollectorJob.getInstance().setEnabled(false);
 
-
-            boolean first = true;           
+            boolean first = true;
             int i = 0;
-            for (Node d : flattened) {
+            for (Node d : flattenedNodes) {
                 ++i;
-                
+
                 //System.out.println("PAGE DESC: " + d.getPageDesc());
                 //System.out.println("PAGE SIZE: " + pageSize);
 
@@ -115,98 +174,96 @@ public class DiagramPrinter {
                 if (writer == null) {
                     document = new Document(pageSize);
                     writer = PdfWriter.getInstance(document, new FileOutputStream(exportPath));
-                   writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
-                   writer.setPageEvent(new ServiceBasedPdfExportPageEvent());
-                   if ( exportPlan.attachTG ) {
-                       writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);
-                   }
+                    writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
+                    writer.setPageEvent(new ServiceBasedPdfExportPageEvent());
+                    if ( exportPlan.attachTG ) {
+                        writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);
+                    }
    
-                   String creator = getCreator();
-                   document.addCreator(creator);
-
-                   /*
-                       File keystoreFile = new File("c:\\0009278.p12");
-                       String password = "ka7GfzI9Oq";
-
-                       try {
-                               KeyStore ks = KeyStore.getInstance("pkcs12");
-                               ks.load(new FileInputStream(keystoreFile), password.toCharArray());
-                               List<String> aliases = Collections.list(ks.aliases());
-                               String alias = aliases.get(0);
-                               PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
-                               Certificate[] chain = ks.getCertificateChain(alias);
-                               int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;
-                               
-                               PdfEncryption crypto = new PdfEncryption();
-                               //for (Certificate c : chain) crypto.addRecipient(c, permission);
-                               //crypto.addRecipient(chain[2], permission);
-                       crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);
-                               crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);
-                       crypto.getEncryptionDictionary();
-                       
-                               
-                       } catch (Exception e) {
-                               e.printStackTrace();
-                       }*/
-                   
-                   /*
-                   writer.setEncryption(
-                               new Certificate[] {}, 
-                               new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, 
-                               PdfWriter.STANDARD_ENCRYPTION_128);
-                               */
-                   //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);
-                       
-                   
-//                     PdfName companyName = new PdfName("SMTC");          
-//                 PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);
-//                 writer.addDeveloperExtension( ext );
-                   
+                    String creator = getCreator();
+                    document.addCreator(creator);
+
+                    /*
+                    File keystoreFile = new File("c:\\0009278.p12");
+                    String password = "ka7GfzI9Oq";
+
+                    try {
+                        KeyStore ks = KeyStore.getInstance("pkcs12");
+                        ks.load(new FileInputStream(keystoreFile), password.toCharArray());
+                        List<String> aliases = Collections.list(ks.aliases());
+                        String alias = aliases.get(0);
+                        PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
+                        Certificate[] chain = ks.getCertificateChain(alias);
+                        int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;
+
+                        PdfEncryption crypto = new PdfEncryption();
+                        //for (Certificate c : chain) crypto.addRecipient(c, permission);
+                        //crypto.addRecipient(chain[2], permission);
+                        crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);
+                        crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);
+                        crypto.getEncryptionDictionary();
+
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }*/
+
+                    /*
+                    writer.setEncryption(
+                            new Certificate[] {}, 
+                            new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, 
+                            PdfWriter.STANDARD_ENCRYPTION_128);
+                            */
+                    //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);
+
+//                    PdfName companyName = new PdfName("SMTC");
+//                    PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);
+//                    writer.addDeveloperExtension( ext );
+
                     document.open();
                 }
 
                 if (!first) {
-                document.setPageSize(pageSize);
-                document.newPage();
+                    document.setPageSize(pageSize);
+                    document.newPage();
                 }
 
                 /*
                 /// ATTACHMENTS - TG ///
                 byte[] attachment = null;
-                       if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() ) 
+                if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() ) 
                 try {
                     PdfDictionary fileParameter = new PdfDictionary();
 
-                       {
-                               final Resource composite = d.getDefiningResources().iterator().next();                                          
-                               final Session session = exportPlan.sessionContext.getSession();
-                               
-                           SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {
-                               @Override
-                               public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {
-                                   CopyHandler ch = graph.adapt(composite, CopyHandler.class);
-                                   SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
-                                   ch.copyToClipboard(graph, clipboard);
-                                   return clipboard;
-                               }
-                           });
-                           for (Set<Representation> object : clipboard.getContents()) {
-                               TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
-                               String filename = d.getName()+".diagram";
-                               try {
-                                       byte[] data = DataContainers.writeFile(                                 
-                                               new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))
-                                       );
-                                           PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
-                                                       writer, 
-                                                       "/Diagram", filename, data, true, "application/simantics/diagram", 
-                                                       fileParameter);
-                                           writer.addFileAttachment(d.getName()+".diagram", fs);
-                               } catch ( NullPointerException npe ) {
-                                       throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);
-                               }
-                           }
-                       }
+                    {
+                        final Resource composite = d.getDefiningResources().iterator().next();
+                        final Session session = exportPlan.sessionContext.getSession();
+
+                        SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {
+                            @Override
+                            public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {
+                                CopyHandler ch = graph.adapt(composite, CopyHandler.class);
+                                SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
+                                ch.copyToClipboard(graph, clipboard);
+                                return clipboard;
+                            }
+                        });
+                        for (Set<Representation> object : clipboard.getContents()) {
+                            TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
+                            String filename = d.getName()+".diagram";
+                            try {
+                                byte[] data = DataContainers.writeFile(
+                                    new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))
+                                );
+                                PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
+                                        writer, 
+                                        "/Diagram", filename, data, true, "application/simantics/diagram", 
+                                        fileParameter);
+                                writer.addFileAttachment(d.getName()+".diagram", fs);
+                            } catch ( NullPointerException npe ) {
+                                throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);
+                            }
+                        }
+                    }
 
                 } catch (DatabaseException e) {
                     e.printStackTrace();
@@ -215,66 +272,50 @@ public class DiagramPrinter {
                 }
                 */
                 //////////////////////////
-                
+
                 String diagramName = formDiagramName(d, true);
-                String subTask = "Page (" + i + "/" + flattened.size() + "): " + diagramName;
+                String subTask = "Page (" + i + "/" + flattenedNodes.size() + "): " + diagramName;
 
                 Resource diagram = d.getDiagramResource();
                 if (diagram == null) {
                     // No diagram, skip page.
                     subTask += " skipped, no diagram.";
-                    System.out.println(subTask);
+                    LOGGER.info(subTask);
                     continue;
                 }
 
-                System.out.println(subTask);
+                LOGGER.info(subTask);
                 progress.subTask(subTask);
 
                 try {
-                    PDFPainter.render(workerThread, sessionContext, exportPlan, d, writer, mapper,
+                    PDFPainter.render(workerThread, exportPlan, d, writer, mapper,
                             pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                } catch (DatabaseException e) {
-                    e.printStackTrace();
+                    ++exportedPages;
+                } catch (DatabaseException | InterruptedException e) {
+                    LOGGER.error("PDF rendering failed.", e);
                 }
 
-                // Paint diagram path/name on the page
-                // TODO: remove this hard coded diagram name printing and
-                // replace it with a page templates that is loaded along with
-                // the rest of the diagram
-
-                int w = (int) pageSize.getWidth();
-                int h = (int) pageSize.getHeight();
-
-                // Write Page Number
-                PdfContentByte cb = writer.getDirectContent();
-
-//                PdfTemplate tp = cb.createTemplate(w, h);
-//                Graphics2D g2d = tp.createGraphics(w, h, mapper);
-//                g2d.setColor(Color.black);
-//                java.awt.Font thisFont = new java.awt.Font("Arial", java.awt.Font.ITALIC, 10);
-//                g2d.setFont(thisFont);
-//                FontMetrics metrics = g2d.getFontMetrics();
-//                int width = metrics.stringWidth(diagramName);
-//                g2d.drawString(diagramName, (w - width) / 2, document.getPageSize().getHeight() - PageDesc.toPoints(5));
-//                g2d.dispose();
-//                cb.addTemplate(tp, 0, 0);
-
                 /// ATTACHMENTS - Write WIKI ///
                 if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) {
-                    final Session session = exportPlan.sessionContext.getSession();
+                    int w = (int) pageSize.getWidth();
+                    int h = (int) pageSize.getHeight();
+                    PdfContentByte cb = writer.getDirectContent();
+                    Session session = exportPlan.sessionContext.getSession();
                     Resource composite = d.getDefiningResources().iterator().next();
                     DocumentUtils du = new DocumentUtils();
                     StringBuilder wiki = new StringBuilder();
                     StringBuilder css = new StringBuilder();
                     du.getDocumentWikiTextRecursive(session, composite, wiki, css);
-                       DocumentSettings settings = du.getDocumentSettings(session, composite);
+                    DocumentSettings settings = du.getDocumentSettings(session, composite);
                     PdfTemplate tp_ = cb.createTemplate(w, h);
                     if ( wiki.length()>0 ) {
                         String wikiText = wiki.toString();
                         String cssText = css.toString();
-                        du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);
+                        try {
+                            exportedPages += du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);
+                        } catch (DatabaseException | DocumentException e) {
+                            LOGGER.error("Wiki documentation to PDF rendering failed.", e);
+                        }
                     }
                     cb.addTemplate(tp_, 0, 0);
                 }
@@ -286,29 +327,27 @@ public class DiagramPrinter {
                 if (progress.isCanceled())
                     throw new OperationCanceledException();
 
-                System.out.println("GC");
+                LOGGER.trace("GC");
                 SVGCache.getSVGUniverse().clearUnreferenced();
-                SessionGarbageCollection.gc(null, sessionContext.getSession(), true, null);
+                SessionGarbageCollection.gc(null, exportPlan.sessionContext.getSession(), true, null);
                 System.gc();
-                System.out.println("GC finished");
+                LOGGER.trace("GC finished");
                 progress.worked(1);
             }
-               } catch (DatabaseException e) {
-                       throw new PdfException(e);
-               } catch (FileNotFoundException e) {
-                       throw new PdfException(e);
-               } catch (DocumentException e) {
-                       throw new PdfException(e);
-               } finally {
+
+            return exportedPages;
+        } catch (DatabaseException | FileNotFoundException | DocumentException | ExceptionConverter e) {
+            throw new PdfException(e);
+        } finally {
             workerThread.stopDispatchingEvents(true);
-            System.out.println("closing document");
+            LOGGER.trace("closing document");
             try {
-               if ( document!=null ) document.close();
-                if ( writer!=null ) writer.close();
-            } catch(RuntimeException e) {
-               e.printStackTrace();
+                if ( document != null ) document.close();
+                if ( writer != null ) writer.close();
+                LOGGER.trace("document closed");
+            } catch (RuntimeException e) {
+                LOGGER.error("Error closing PDF document writer", e);
             }
-            System.out.println("document closed");
             SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();
         }
     }
@@ -341,23 +380,23 @@ public class DiagramPrinter {
         return ret;
     }
 
-       public static String getCreator() {
-               String creator = null;
-               IProduct product = Platform.getProduct();
-               if (product != null) {
-                       creator = product.getDescription();
-                       if (creator == null) {
-                               creator = product.getName();
-                       }
-               }
-               if (creator == null) {
-                       creator = "Simantics";
-               }
-               return creator;
-       }
+    public static String getCreator() {
+        String creator = null;
+        IProduct product = Platform.getProduct();
+        if (product != null) {
+            creator = product.getDescription();
+            if (creator == null) {
+                creator = product.getName();
+            }
+        }
+        if (creator == null) {
+            creator = "Simantics";
+        }
+        return creator;
+    }
 
     static {
-               Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
     }
 
 }
\ No newline at end of file
index ba389f77d3cd149d96e8c4d3db788b06983edb8e..f0c9cddb32514610ec850b0bb9b30919e5657516 100644 (file)
@@ -260,9 +260,7 @@ public class PDFDiagramExportWizard extends Wizard implements IExportWizard {
                 @Override
                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                     try {
-                       // Print pdf
-                        DiagramPrinter.printToPdf(monitor, exportPlan, exportPlan.exportLocation.toString(), exportPlan.selectedNodes, exportPlan.sessionContext);
-                        
+                        DiagramPrinter.printToPdf(monitor, exportPlan, exportPlan.exportLocation.toString(), exportPlan.selectedNodes);
                     } catch (PdfException e) {
                         throw new InvocationTargetException(e);
                     } finally {
index 88312f67fe27ba54c1ce539e727af99f31811093..a41715f3bc81e64d4eabb0c44323c523541b7c6c 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 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
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - (#7084) page numbering
  *******************************************************************************/
 package org.simantics.modeling.ui.pdf;
 
@@ -20,6 +21,7 @@ import java.util.Set;
 
 import org.simantics.db.common.NamedResource;
 import org.simantics.db.management.ISessionContext;
+import org.simantics.export.core.pdf.PageNumbering;
 import org.simantics.modeling.requests.CollectionResult;
 import org.simantics.modeling.requests.Node;
 import org.simantics.project.IProject;
@@ -63,8 +65,26 @@ public class PDFExportPlan {
      * <code>true</code> to attach Wiki page.
      */
     public boolean attachWiki = false;
-    
-    
+
+    /**
+     * Whether or not to add page numbers to the exported PDF. Default value is
+     * {@value #addPageNumbers}.
+     * 
+     * @since 1.28.0
+     */
+    public boolean addPageNumbers = true;
+
+    /**
+     * This is ignored if {@link #addPageNumbers} is <code>false</code>.
+     */
+    public PageNumbering.Position pageNumberPosition = PageNumbering.Position.BOTTOM_RIGHT;
+
+    /**
+     * This is ignored if {@link #addPageNumbers} is <code>false</code>.
+     */
+    public PageNumbering.NumberingFormat pageNumberFormat = PageNumbering.NumberingFormat.PAGE_SLASH_TOTAL_PAGES;
+
+
     public PDFExportPlan(ISessionContext sessionContext, Collection<String> recentLocations) {
         this.sessionContext = sessionContext;
         this.recentLocations = recentLocations;
index 85cf4bc08a801fe109b2ce5bf8bc1514b3d159e5..1adcf25c23d33a2b2f7ede11eaf9210697097fb6 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 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
@@ -8,14 +8,15 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - (#7084) refactoring
  *******************************************************************************/
 package org.simantics.modeling.ui.pdf;
 
 import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
+import org.simantics.db.Session;
 import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.common.utils.NameUtils;
@@ -23,7 +24,7 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ValidationException;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
-import org.simantics.db.management.ISessionContext;
+import org.simantics.db.request.Read;
 import org.simantics.diagram.elements.DiagramNodeUtil;
 import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.g2d.canvas.Hints;
@@ -31,7 +32,6 @@ import org.simantics.g2d.canvas.impl.CanvasContext;
 import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
 import org.simantics.modeling.requests.Node;
 import org.simantics.structural.stubs.StructuralResource2;
-import org.simantics.utils.DataContainer;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.page.PageDesc;
 import org.simantics.utils.threads.IThreadWorkQueue;
@@ -48,9 +48,8 @@ import com.lowagie.text.pdf.PdfWriter;
  */
 public class PDFPainter {
 
-    public static boolean render(
+    public static void render(
             final IThreadWorkQueue thread,
-            final ISessionContext sessionContext,
             PDFExportPlan exportModel,
             final Node node,
             final PdfWriter writer,
@@ -59,105 +58,101 @@ public class PDFPainter {
             final PageDesc pageDesc,
             final boolean fitDiagramContentsToPageMargins,
             long timeout)
-    throws InterruptedException, DatabaseException
+                    throws InterruptedException, DatabaseException
     {
-        final DataContainer<Boolean> result = new DataContainer<Boolean>(false);
-        final DataContainer<DatabaseException> exception = new DataContainer<DatabaseException>();
+        DatabaseException[] exception = { null };
+        ICanvasSceneGraphProvider[] sgProvider = { null };
 
-        final CanvasContext ctx = new CanvasContext(thread);
-        final AtomicReference<ICanvasSceneGraphProvider> sgProvider = new AtomicReference<ICanvasSceneGraphProvider>();
+        CanvasContext ctx = new CanvasContext(thread);
 
         try {
             final Semaphore done = new Semaphore(0);
             // IMPORTANT: Load diagram in a different thread than the canvas context thread!
-            ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        Pair<Resource, String> modelAndRVI = sessionContext.getSession().syncRequest(new UniqueRead<Pair<Resource, String>>() {
-                            @Override
-                            public Pair<Resource, String> perform(ReadGraph graph) throws DatabaseException {
-                                return new Pair<Resource, String>( resolveModel(graph, node), resolveRVI(graph, node) );
-                            }
-                        });
-                        
-                        final Boolean isSymbol = sessionContext.getSession().syncRequest(new UniqueRead<Boolean>() {
-                            @Override
-                            public Boolean perform(ReadGraph graph) throws DatabaseException {
-                               StructuralResource2 STR = StructuralResource2.getInstance(graph);
-                               DiagramResource DIA = DiagramResource.getInstance(graph);
-                               Resource possibleSymbol = graph.getPossibleObject(node.getDiagramResource(), STR.Defines);
-                               return possibleSymbol != null && graph.isInstanceOf(possibleSymbol, DIA.ElementClass);
-                            }
-                        }); 
-                        
-                        ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(ctx, modelAndRVI.first, node.getDiagramResource(), modelAndRVI.second, 5000);
-                        sgProvider.set( provider );
-                        ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
-
-//                        StringBuilder b = new StringBuilder();
-//                        NodeUtil.printTreeNodes(ctx.getCanvasNode(), b);
-//                        System.err.println(b.toString());
-
-                        ThreadUtils.asyncExec(thread, new Runnable() {
-                            @Override
-                            public void run() {
-                                try {
-                                    PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitDiagramContentsToPageMargins || isSymbol);
-                                    
-                                    chassis.paint(ctx, true);
-                                } finally {
-                                    done.release();
-                                }
-                            }
-                        });
-                    } catch (DatabaseException e) {
-                        done.release();
-                        exception.set(e);
-                    } catch (Throwable e) {
-                        done.release();
-                        exception.set(new DatabaseException(e));
-                    } finally {
-                        done.release();
-                    }
+            ThreadUtils.getBlockingWorkExecutor().execute(() -> {
+                try {
+                    Session s = exportModel.sessionContext.getSession();
+
+                    Pair<Resource, String> modelAndRVI = s.syncRequest( modelAndRVI(node) );
+                    Boolean isSymbol = s.syncRequest( isSymbol(node) ); 
+
+                    ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(
+                            ctx,
+                            modelAndRVI.first,
+                            node.getDiagramResource(),
+                            modelAndRVI.second,
+                            5000);
+                    sgProvider[0] = provider;
+                    ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
+
+//                    System.err.println(NodeUtil.printTreeNodes(ctx.getCanvasNode(), new StringBuilder()).toString());
+
+                    ThreadUtils.asyncExec(thread, () -> {
+                        try {
+                            PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitDiagramContentsToPageMargins || isSymbol);
+                            chassis.paint(ctx, true);
+                        } catch (Throwable e) {
+                            exception[0] = new DatabaseException(e);
+                        } finally {
+                            done.release();
+                        }
+                    });
+                } catch (DatabaseException e) {
+                    done.release();
+                    exception[0] = e;
+                } catch (Throwable e) {
+                    done.release();
+                    exception[0] = new DatabaseException(e);
+                } finally {
+                    done.release();
                 }
             });
 
             done.acquire(2);
-            if (exception.get() != null)
-                throw exception.get();
-            return result.get();
+            if (exception[0] != null)
+                throw exception[0];
         } finally {
-            if (sgProvider.get() != null)
-                sgProvider.get().dispose();
+            if (sgProvider[0] != null)
+                sgProvider[0].dispose();
             ctx.dispose();
         }
     }
 
+    private static Read<Pair<Resource, String>> modelAndRVI(Node node) {
+        return new UniqueRead<Pair<Resource, String>>() {
+            @Override
+            public Pair<Resource, String> perform(ReadGraph graph) throws DatabaseException {
+                return Pair.make( resolveModel(graph, node), resolveRVI(graph, node) );
+            }
+        };
+    }
+
+    private static Read<Boolean> isSymbol(Node node) {
+        return new UniqueRead<Boolean>() {
+            @Override
+            public Boolean perform(ReadGraph graph) throws DatabaseException {
+                StructuralResource2 STR = StructuralResource2.getInstance(graph);
+                DiagramResource DIA = DiagramResource.getInstance(graph);
+                Resource possibleSymbol = graph.getPossibleObject(node.getDiagramResource(), STR.Defines);
+                return possibleSymbol != null && graph.isInstanceOf(possibleSymbol, DIA.ElementClass);
+            }
+        };
+    }
+
     private static Resource resolveModel(ReadGraph graph, Node node) throws DatabaseException {
         Resource composite = node.getDefiningResources().head();
         Resource model = graph.syncRequest(new PossibleIndexRoot(composite));
-//        Resource model = StructuralVariables.getModel(graph, composite);
         if (model == null)
             throw new ValidationException("no model found for composite " + NameUtils.getSafeName(graph, composite));
         return model;
     }
 
-//    private static String resolveModelURI(ReadGraph graph, final Node node) throws DatabaseException {
-//        return graph.getURI(resolveModel(graph, node));
-//    }
-
     private static String resolveRVI(ReadGraph graph, final Node node) throws DatabaseException {
-       String RVI = node.getRVI();
-       if(RVI != null) return RVI;
+        String RVI = node.getRVI();
+        if (RVI != null) return RVI;
         Resource composite = node.getDefiningResources().head();
         Variable var = Variables.getVariable(graph, composite);
         org.simantics.db.layer0.variable.RVI rvi = var.getPossibleRVI(graph);
-        if(rvi == null) return null;
-        return rvi.toString();
-//        final ResourceArray compositePath = StructuralVariables.getCompositeArray(graph, composite);
-//        final ResourceArray variablePath = compositePath.removeFromBeginning(1);
-//        return StructuralVariables.getRVI(graph, variablePath);
+        return rvi != null ? rvi.toString() : null;
     }
 
-}
+}
\ No newline at end of file
index 95beaad384a7eb6f8a543d6aaf48030c54e6bf7c..df65646346386755b7cecc2388350ac74824a652 100644 (file)
@@ -27,6 +27,7 @@ import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.wizard.Wizard;
 import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
 import org.eclipse.ui.IImportWizard;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.preferences.ScopedPreferenceStore;
@@ -37,6 +38,7 @@ import org.simantics.databoard.container.DataContainers;
 import org.simantics.databoard.container.FormatHandler;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
+import org.simantics.db.layer0.migration.MigratedImportResult;
 import org.simantics.db.layer0.migration.MigrationUtils;
 import org.simantics.db.layer0.util.DraftStatusBean;
 import org.simantics.db.management.ISessionContext;
@@ -48,8 +50,10 @@ import org.simantics.project.IProject;
 import org.simantics.project.ProjectKeys;
 import org.simantics.ui.SimanticsUI;
 import org.simantics.ui.utils.ResourceAdaptionUtils;
+import org.simantics.utils.strings.EString;
 import org.simantics.utils.ui.ErrorLogger;
 import org.simantics.utils.ui.ExceptionUtils;
+import org.simantics.utils.ui.dialogs.InfoDialog;
 
 /**
  * @author Tuukka Lehtonen
@@ -123,13 +127,14 @@ public class SharedOntologyImportWizard extends Wizard implements IImportWizard
         }
 
         try {
+            MigratedImportResult[] result = { null };
             getContainer().run(true, true, new IRunnableWithProgress() {
                 @Override
                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                     try {
                         Resource target = ResourceAdaptionUtils.toSingleResource(importModel.selection);
                         importModel.sessionContext.getSession().markUndoPoint();
-                        doImport(monitor, importModel.importLocation, importModel.sessionContext.getSession(), target);
+                        result[0] = doImport(monitor, importModel.importLocation, importModel.sessionContext.getSession(), target);
                     } catch (Exception e) {
                         throw new InvocationTargetException(e);
                     } finally {
@@ -137,6 +142,13 @@ public class SharedOntologyImportWizard extends Wizard implements IImportWizard
                     }
                 }
             });
+
+            if (result[0].hasMissingExternals()) {
+                InfoDialog.open(getShell(), "Missing Externals Created",
+                        "The system was unable to find some of the external entities referenced by the imported material. Place-holders have been created for the missing entities.\nThe missing entities are:\n"
+                                + EString.implode(result[0].tgResult.missingExternals),
+                        SWT.SHEET);
+            }
         } catch (InvocationTargetException e) {
             Throwable cause = e.getCause();
             WizardPage cp = (WizardPage) getContainer().getCurrentPage();
@@ -161,37 +173,38 @@ public class SharedOntologyImportWizard extends Wizard implements IImportWizard
         return true;
     }
 
-    public static void doImport(IProgressMonitor monitor, File modelFile, Session session, Resource target)
+    public static MigratedImportResult doImport(IProgressMonitor monitor, File modelFile, Session session, Resource target)
             throws Exception
     {
         SubMonitor mon = SubMonitor.convert(monitor);
         mon.beginTask("Loading shared library from disk", 1000);
 
-        FormatHandler<Object> handler1 = new FormatHandler<Object>() {
+        FormatHandler<MigratedImportResult> handler1 = new FormatHandler<MigratedImportResult>() {
             @Override
             public Binding getBinding() {
                 return TransferableGraph1.BINDING;
             }
 
             @Override
-            public Object process(DataContainer container) throws Exception {
+            public MigratedImportResult process(DataContainer container) throws Exception {
                 mon.worked(100);
                 mon.setTaskName("Importing shared library into database");
                 Variant draftStatus = container.metadata.get(DraftStatusBean.EXTENSION_KEY);
                 TransferableGraph1 tg = (TransferableGraph1) container.content.getValue();
-                MigrationUtils.importSharedOntology(mon.newChild(850, SubMonitor.SUPPRESS_NONE), session, tg, draftStatus == null);
-                return null;
+                return MigrationUtils.importSharedOntology(mon.newChild(850, SubMonitor.SUPPRESS_NONE), session, tg, draftStatus == null);
             }
         };
 
-        Map<String, FormatHandler<Object>> handlers = new HashMap<>();
+        Map<String, FormatHandler<MigratedImportResult>> handlers = new HashMap<>();
         handlers.put(Constants.SHARED_LIBRARY_FORMAT_V1, handler1);
 
-        DataContainers.readFile(modelFile, handlers);
+        MigratedImportResult result = DataContainers.readFile(modelFile, handlers);
 
         mon.setTaskName("Postprocessing");
         mon.subTask("");
         mon.newChild(50).done();
+
+        return result;
     }
 
 }
index 5245ed47e7665fb1abe384033ad087367844f446..7f81e56f2300bc0511473436e2494932e4b8af15 100644 (file)
@@ -37,7 +37,8 @@ Require-Bundle: org.simantics.simulation;bundle-version="1.0.0",
  org.simantics.scl.db;bundle-version="0.1.3",
  org.simantics.selectionview.ontology;bundle-version="1.2.0",
  org.simantics.scl.ui;bundle-version="0.5.0",
- org.slf4j.api
+ org.slf4j.api,
+ org.apache.batik
 Export-Package: org.simantics.modeling,
  org.simantics.modeling.actions,
  org.simantics.modeling.adapters,
index 0ea0459599439030a1b1915ecea72f37e5c4e330..02457e67f0811baac1465e760e143d32bdaac768 100644 (file)
@@ -25,6 +25,7 @@ include "Simantics/Query"
 include "Simantics/Datatypes"
 include "Spreadsheet/All"
 include "Simantics/WorkbenchSelection"
+include "Simantics/Workbench"
 include "Simantics/Structural"
 include "SWT/All"
 include "Simantics/UI"
index 2490acc5b916b52ccd6e05e8b26accfcf15abce8..6e04a6f6d6f4c6e21cbc9e94d3fae840786838ae 100644 (file)
@@ -140,18 +140,18 @@ hasRandomIdentifier entity = runProc (claimRelatedValue_ entity L0.identifier GU
 diagramsOf :: Model -> <ReadGraph> [Diagram]
 diagramsOf model = recurse
                    DIA.Diagram 
-                   (toResource (configurationOf model))
+                   (configurationOf model)
   where
     recurse t r = do
-        cs = resourceChildrenOf r 
-        dias = map fromResource $ filter isDiagramComposite cs
+        cs = children r 
+        dias = filter isDiagramComposite cs
         folders = filter (not . isDiagramComposite) cs
         dias + concatMap (recurse t) folders
     isDiagramComposite r = existsStatement r MOD.CompositeToDiagram
 
 """Returns a model relative path of the given diagram."""
 pathOf :: Diagram -> <ReadGraph> [String]
-pathOf diagram = map nameOf $ unfoldl aux $ toResource diagram
+pathOf diagram = map nameOf $ unfoldl aux diagram
   where
     aux r = if existsStatement r SIMU.IsConfigurationOf
             then Nothing
@@ -169,7 +169,7 @@ pathNameOf diagram = do
 
 // @Private?
 diagramResourceOf :: Diagram -> <ReadGraph> Resource
-diagramResourceOf d = singleObject (toResource d) MOD.CompositeToDiagram
+diagramResourceOf d = singleObject d MOD.CompositeToDiagram
 
 import "Extras/HashMap" as Map
 
@@ -214,11 +214,11 @@ compositeToDiagram' c = singleObject c MOD.CompositeToDiagram
 """Creates or modifies an existing diagram to contain the given diagram elements."""        
 createDiagramR :: DiagramSpec -> (Dynamic -> <WriteGraph> Resource) -> [DiagramElement Resource] -> <WriteGraph> (Diagram, [Resource])
 createDiagramR (ExistingDiagram diagram') joinMap elementSpecs = runProc do
-    configuration = toResource diagram'
+    configuration = diagram'
     diagram = compositeToDiagram' configuration
     hasName = L0.HasName
     componentMap = Map.fromList [ (c `relatedValue` hasName :: String, c)
-                                | c <- resourceChildrenOf configuration
+                                | c <- children configuration
                                 ]
     denyByPredicate diagram L0.ConsistsOf
     elements = setElements (DiagramInfo diagram configuration componentMap) joinMap elementSpecs
@@ -232,12 +232,12 @@ createDiagramR (NewDiagram model path folderType compositeType) joinMap elementS
     elements = setElements (DiagramInfo diagram configuration (Map.create ())) joinMap elementSpecs
     claimRelatedValue diagram DIA.HasModCount 
         (fromInteger (length elements) :: Long)
-    (fromResource configuration, elements)
+    (configuration, elements)
 ) where
     createConfiguration () = do
         lastId = length path - 1
         parentFolder = foldl (\p id -> getOrCreateFolder p (path!id)) 
-            (toResource (configurationOf model)) 
+            (configurationOf model)
             [0..lastId-1]        
         createComposite_ parentFolder (path!lastId) compositeType
     getOrCreateFolder parentFolder name =
@@ -250,14 +250,14 @@ claimFolder :: Model -> [String] -> Resource -> <Proc,WriteGraph> Resource
 claimFolder model path folderType = do
     lastId = length path
     foldl (\p id -> getOrCreateFolder p folderType (path!id)) 
-        (toResource (configurationOf model)
+        (configurationOf model
         [0..lastId-1]
 
 claimModelFolder :: Model -> [String] -> Resource -> <Proc,WriteGraph> Resource
 claimModelFolder model path folderType = do
     lastId = length path
     foldl (\p id -> getOrCreateFolder p folderType (path!id)) 
-        (toResource model) 
+        model
         [0..lastId-1]        
 
 getOrCreateFolder :: Resource -> Resource -> String -> <Proc,WriteGraph> Resource
@@ -554,21 +554,21 @@ setElements (DiagramInfo diagram configuration componentMap) joinMap elementSpec
 """Returns a diagram in the given model with the given model relative path.""" 
 diagram :: Model -> [String] -> <ReadGraph> Diagram
 diagram model path = 
-    fromResource $ foldl 
+    foldl 
         (\r name -> match possibleResourceChild r name with
             Just c -> c
             Nothing -> fail ("Didn't find " + name + ".") 
         ) 
-        (toResource (configurationOf model)) path
+        (configurationOf model) path
 
 possibleDiagram :: Model -> [String] -> <ReadGraph> (Maybe Diagram)
 possibleDiagram model path = 
-    map fromResource (foldl
+    foldl
         (\r name -> match r with
             Just p -> possibleResourceChild p name
             Nothing -> Nothing 
         ) 
-        (Just $ toResource (configurationOf model)) path)
+        (Just (configurationOf model)) path
 
 /*
 """FIXME: doesn't work anymore with the elementsOfR spec
@@ -757,7 +757,7 @@ importJava "org.simantics.modeling.typicals.TypicalUtil" where
     
 syncActivateDiagram :: Diagram -> <WriteGraph, Proc> Boolean
 syncActivateDiagram composite = do
-    diagram = compositeToDiagram' $ toResource composite
+    diagram = compositeToDiagram' composite
     syncActivateOnce diagram
     True
 
@@ -768,25 +768,21 @@ importJava "org.simantics.structural2.utils.StructuralUtils" where
     createComposite__ :: Configuration -> String -> Resource -> <WriteGraph> Diagram
 
 compositeToDiagram :: Resource -> <ReadGraph> Diagram
-compositeToDiagram c = fromResource (singleObject c MOD.CompositeToDiagram) 
+compositeToDiagram c = singleObject c MOD.CompositeToDiagram
 
 createComposite :: Configuration -> String -> Resource -> <WriteGraph> Diagram
 createComposite diagramFolder name compositeType = do
-     newName = findFreshName name (toResource diagramFolder)
+     newName = findFreshName name diagramFolder
      createComposite__ diagramFolder newName compositeType
 
 elementToComponent :: Element -> <ReadGraph> Component
-elementToComponent element = do
-    component = singleObject (toResource element) MOD.ElementToComponent
-    fromResource component
+elementToComponent element = singleObject element MOD.ElementToComponent
     
 componentToElement :: Component -> <ReadGraph> Element
-componentToElement component = do
-    element = singleObject (toResource component) MOD.ComponentToElement
-    fromResource element
+componentToElement component = singleObject component MOD.ComponentToElement
 
 getConnections :: Diagram -> <ReadGraph> [Resource]
-getConnections diagram = [object | object <- (toResource $ compositeToDiagram $ toResource diagram) # L0.ConsistsOf, isInstanceOf object DIA.RouteGraphConnection]
+getConnections diagram = [object | object <- (compositeToDiagram diagram) # L0.ConsistsOf, isInstanceOf object DIA.RouteGraphConnection]
 
 getConnection :: Diagram -> String -> <ReadGraph> [Resource]
 getConnection diagram name = do
index c11fc532d9697f85a20dec90fa287361513a2442..a612aca96cc089003b0aa514e932ee32d9ade642 100644 (file)
@@ -50,7 +50,7 @@ translateDiagrams (sourceModel :: Model)
                       $ sourceDiagram
   
   for targetDiagrams $ \diagram ->
-    syncActivateOnce $ toResource diagram
+    syncActivateOnce diagram
     
   doElementPostProcessing elementMap elementPostProcessing
 
@@ -74,7 +74,7 @@ translateDiagram (sourceModel :: Model)
 possibleDrawingTemplate :: Model -> Diagram -> <ReadGraph> Maybe Resource
 possibleDrawingTemplate model d = do
     d' = diagramResourceOf d
-    library = fromJust $ possibleResourceChild (toResource model) "Diagram Templates"
+    library = fromJust $ possibleResourceChild model "Diagram Templates"
     match (possibleObject d' TMPL.HasDrawingTemplate) with
         Just dt -> match (possibleNameOf dt) with
             Just name -> possibleResourceChild library name
@@ -102,7 +102,7 @@ store elementMap a b c = do
   ()
 
 getTargetComponent (targetDiagram :: Diagram) (sourceComponent :: Resource) =
-    (possibleResourceChild (toResource targetDiagram) (fromJust $ possibleNameOf sourceComponent)) :: Maybe Resource
+    (possibleResourceChild targetDiagram (fromJust $ possibleNameOf sourceComponent)) :: Maybe Resource
 
 translateDiagram2 (targetModel :: Model)  
                   (sourceDiagram :: Diagram) 
index 61eb7bd645ebe68cd6bc9b71e7ab0202d554fc6e..4cf5298722c42ad25455232200dc439ad4255d7d 100644 (file)
@@ -6,8 +6,9 @@ type Flag = Resource
 
 // FLAGS ---------------------------
 
+@deprecated "Unnecessary function."
 toFlag :: Resource -> Flag
-toFlag flag = (fromResource flag)
+toFlag flag = flag
 
 importJava "org.simantics.modeling.flags.MergeFlags" where
     @JavaName mergeFlags
@@ -34,21 +35,20 @@ joinFlags flag1 flag2 = do
         hasType STR.ConnectionJoin,
         hasStatement 
             DIA.JoinsFlag
-            (toResource flag1),
+            flag1,
         hasStatement
             DIA.JoinsFlag
-            (toResource flag2)
+            flag2
     ]
     ()
 
+@deprecated "Unnecessary function."
 flagToElement :: Flag -> Element
-flagToElement flag = do
-    flagResource = toResource flag
-    fromResource flagResource
+flagToElement flag = flag
 
 getFlags :: Diagram -> <ReadGraph> [Resource]
 getFlags dia = do
-    children = collectionToList (objects_ (singleObject (toResource dia) MOD.CompositeToDiagram) L0.ConsistsOf)
+    children = collectionToList (objects_ (singleObject dia MOD.CompositeToDiagram) L0.ConsistsOf)
     flags = filter (\x -> isInstanceOf x DIA.Flag) children
     flags
    
index c7628bc93cfaf2853af0033e561d2c4b5ddf8d27..e09297750d680e90d2bc55081e285d6d3f12fa45 100644 (file)
@@ -6,11 +6,11 @@ type Issue = Resource
 type Severity = Resource
     
 issuesOf :: Model -> <ReadGraph> [Issue]
-issuesOf model = recurse ISSUE.Issue (toResource model)
+issuesOf model = recurse ISSUE.Issue model
   where
     recurse t r = do
-        cs = resourceChildrenOf r 
-        issues = map fromResource $ filter isIssue cs
+        cs = children r 
+        issues = filter isIssue cs
         issueGrp = filter (not . isIssue) cs
         issues + concatMap (recurse t) issueGrp
     isIssue r = isInstanceOf r ISSUE.Issue
index a2531e3e07a7060e02d9e5cab2a505611e771b8d..c631d399e99e18a4a17825538b312bd41f634ab4 100644 (file)
@@ -11,7 +11,7 @@ Returns an existing model in the current project with the given `name`
 """
 model :: String -> <ReadGraph> Model
 model name = match possibleResourceChild (currentProject ()) name with
-    Just m -> fromResource m
+    Just m -> m
     Nothing -> fail $ "Didn't find a model " + name + "." 
 
 """
@@ -21,15 +21,13 @@ Returns the configuration of the given `model`
 and returns the `configuration` resource
 """
 configurationOf :: Model -> <ReadGraph> Configuration
-configurationOf m = do
-    conf = singleObject (toResource m) SIMU.HasConfiguration 
-    fromResource conf
+configurationOf m = singleObject m SIMU.HasConfiguration
 
 """
 Returns the list of all models in the current project.
 """
 allModels :: () -> <ReadGraph> [Model]
-allModels _ = map fromResource $ objectsWithType (currentProject ()) L0.ConsistsOf SIMU.Model
+allModels _ = objectsWithType (currentProject ()) L0.ConsistsOf SIMU.Model
 
 importJava "org.simantics.modeling.ModelingUtils" where
     """Removes the index associated with the model."""
index 8199a000efa7dfc6b09b76e4204d993870861052..cb048e037ff672cb87841f22bd53adab9316866f 100644 (file)
@@ -30,9 +30,9 @@ Example:
     
 or error if failed
 """
+@deprecated "This function is equivalent to renameNode."
 renameMBNode :: Resource -> String -> <WriteGraph> String
-renameMBNode entity newname = do
-    renameNode (toResource entity) newname
+renameMBNode entity newname = renameNode entity newname
 
 importJava "org.simantics.db.common.utils.NameUtils" where
     @JavaName findFreshName
index dae67434e9d2a64a1463f384378812e8b8e73c6f..5e0e830752c5a3869655a6c3101b4311e4c182cf 100644 (file)
@@ -51,13 +51,15 @@ importJava "org.simantics.modeling.SCLScenegraph" where
     editNodeText :: ICanvasContext -> String -> String -> String -> <Proc> String
     
     copyPaste :: ICanvasContext -> ICanvasContext -> [Resource] -> <Proc> Boolean
+    
+    renderSVG :: ICanvasContext -> <Proc> String
 
 getSceneGraphProvider :: Diagram -> <Proc> ICanvasSceneGraphProvider
 getSceneGraphProvider diagram = do
-    diagramName = syncRead(\() -> getSafeName (toResource diagram))
+    diagramName = syncRead(\() -> getSafeName diagram)
     diagramRVI = "/" + diagramName
-    model = syncRead(\() -> getPossibleModel (toResource diagram))
-    composite = syncRead(\() -> compositeToDiagram' (toResource diagram))
+    model = syncRead(\() -> fromJust $ possibleIndexRoot diagram)
+    composite = syncRead(\() -> compositeToDiagram' diagram)
     getICanvasSceneGraphProvider model composite diagramRVI
 
 getDiagramContext :: ICanvasSceneGraphProvider -> ICanvasContext
@@ -66,30 +68,30 @@ getDiagramContext provider = do
     
 getNodeTransform :: Diagram -> String -> <Proc> String
 getNodeTransform diagram nodeName = do
-    diagramName = syncRead(\() -> getSafeName (toResource diagram))
+    diagramName = syncRead(\() -> getSafeName diagram)
     diagramRVI = "/" + diagramName
-    model = syncRead(\() -> getPossibleModel (toResource diagram))
-    composite = syncRead(\() -> compositeToDiagram' (toResource diagram))
+    model = syncRead(\() -> getPossibleModel diagram)
+    composite = syncRead(\() -> compositeToDiagram' diagram)
     provider = getICanvasSceneGraphProvider model composite diagramRVI
     context = getCanvasContext provider
     getTransform context nodeName
     
 getNodeText :: Diagram -> String -> <Proc> String
 getNodeText diagram nodeName = do
-    diagramName = syncRead(\() -> getSafeName (toResource diagram))
+    diagramName = syncRead(\() -> getSafeName diagram)
     diagramRVI = "/" + diagramName
-    model = syncRead(\() -> getPossibleModel (toResource diagram))
-    composite = syncRead(\() -> compositeToDiagram' (toResource diagram))
+    model = syncRead(\() -> getPossibleModel diagram)
+    composite = syncRead(\() -> compositeToDiagram' diagram)
     provider = getICanvasSceneGraphProvider model composite diagramRVI
     context = getCanvasContext provider
     getText context nodeName
 
 getNodeCount :: Diagram -> <Proc> String
 getNodeCount diagram = do
-    diagramName = syncRead(\() -> getSafeName (toResource diagram))
+    diagramName = syncRead(\() -> getSafeName diagram)
     diagramRVI = "/" + diagramName
-    model = syncRead(\() -> getPossibleModel (toResource diagram))
-    composite = syncRead(\() -> compositeToDiagram' (toResource diagram))
+    model = syncRead(\() -> getPossibleModel diagram)
+    composite = syncRead(\() -> compositeToDiagram' diagram)
     provider = getICanvasSceneGraphProvider model composite diagramRVI
     context = getCanvasContext provider 
     getCount context
index 4935fafcd043c547853d18984e15eab1380e272c..72166303ea6ec97967454ac9607671dbaf1af7b7 100644 (file)
@@ -6,10 +6,15 @@ importJava "org.simantics.simulation.experiment.ExperimentUtil" where
     stepExperiment :: IExperiment -> Double -> <Proc> ()
     simulateExperiment :: IExperiment -> Boolean -> <Proc> ()
     disposeExperiment :: IExperiment -> <Proc> ()
-    possibleActiveRunVariable ::Resource -> <ReadGraph> Variable
+    getExperimentState :: IExperiment -> <ReadGraph> ExperimentState
+    possibleActiveRunVariable ::Resource -> <ReadGraph> Maybe Variable
     
 importJava "org.simantics.simulation.experiment.IExperiment" where
     data IExperiment
+
+importJava "org.simantics.simulation.experiment.ExperimentState" where
+    data ExperimentState
+    INITIALIZING, RUNNING, STOPPED, DISPOSED :: ExperimentState
     
 experimentFromRun :: Variable -> <ReadGraph> IExperiment
 experimentFromRun run = (run#iExperiment) :: IExperiment
\ No newline at end of file
index 111e88b015f72842d5950462141a66a25c7a7d80..01bc3f0580a4f366d8a85b00cdb5a322507831f5 100644 (file)
@@ -196,10 +196,7 @@ Example: Model contains two subscription folders called **Default** and **Pressu
 
 """
 subscriptionFoldersOf :: Model -> <ReadGraph> [SubscriptionFolder]
-subscriptionFoldersOf model = recurse (toResource model)
+subscriptionFoldersOf model = recurse model
   where
-    recurse r = do
-        cs = resourceChildrenOf r
-        folders = map fromResource $ filter isSubscriptionFolder cs
-        folders
+    recurse r = filter isSubscriptionFolder (children r)
     isSubscriptionFolder r = isInstanceOf r MOD.Subscription
index a4c834b4fad74d0c78a080efa071744df1095c17..ad62e1d6a3effcae29504af0ddab77c399cef685 100644 (file)
@@ -1,6 +1,7 @@
 include "Simantics/Model"
 import "Simantics/Diagram"
 import "Simantics/Flag"
+import "Simantics/Workbench"
 include "Simantics/Ontologies"
 
 type UserComponent = Resource
@@ -13,7 +14,7 @@ importJava "org.simantics.modeling.NewComponentType" where
     
 configurationOfComponentType :: UserComponent -> <ReadGraph> Resource
 configurationOfComponentType component = do
-      config = singleObject (toResource component) STR.IsDefinedBy 
+      config = singleObject component STR.IsDefinedBy 
       config
       
 importJava "org.simantics.modeling.flags.LiftFlag" where
@@ -21,19 +22,18 @@ importJava "org.simantics.modeling.flags.LiftFlag" where
     
 flagToTerminal :: Flag -> <WriteGraph> Resource
 flagToTerminal flag = do
-    result = liftFlag (toResource flag)
+    result = liftFlag flag
     if result == Nothing
-    then singleObject (toResource flag) DIA.IsLiftedAs
-    else do
-        show result
-        (toResource flag)
-    
+    then singleObject flag DIA.IsLiftedAs
+    else flag
+
+@deprecated "Calling this function is unnecessary."  
 configToDiagram :: Resource -> Diagram
-configToDiagram config = do
-    fromResource config
+configToDiagram config = config
 
 populateTerminalToSymbol :: Resource  -> (Double, Double) -> <WriteGraph> Element
-populateTerminalToSymbol terminal (x, y) = do
+populateTerminalToSymbol terminal (x, y) = element
+  where
     uc = singleObject terminal L0.PartOf
     symbol = singleObject uc MOD.ComponentTypeToSymbol
     diagram = singleObject symbol STR.IsDefinedBy
@@ -59,7 +59,7 @@ populateTerminalToSymbol terminal (x, y) = do
         (toDoubleArray [1,0,0,1,x,y])
     addToGraph diagram terminal element
     addCommentMetadata ("Populated terminal " + (show element) + " to user component " + (show uc))
-    (fromResource element)
+    
 
 importJava "org.simantics.modeling.symbolEditor.PopulateTerminal" where
     addToGraph :: Resource -> Resource -> Resource -> <WriteGraph> ()
@@ -133,3 +133,29 @@ addUserComponentScript userComponent scriptName scriptType scriptCode = do
     claimRelatedValue script L0.HasName scriptName
     claimRelatedValue script STR.ComponentTypeScript.type scriptType 
     claimRelatedValue script STR.ComponentTypeScript.code scriptCode 
+
+@private
+possibleSubstructure :: Resource -> <ReadGraph> Maybe Resource
+possibleSubstructure element = do
+     match possibleObject element MOD.ElementToComponent with
+       Nothing -> Nothing
+       Just component -> match possibleTypeOf component STR.Component with
+         Nothing -> Nothing
+         Just componentType -> match possibleObject componentType STR.IsDefinedBy with
+           Nothing -> Nothing
+           Just configuration -> Just configuration
+
+@private
+possibleSubstructureEditor :: Resource -> <ReadGraph,Proc> Maybe (Resource,EditorAdapter)
+possibleSubstructureEditor element = match possibleSubstructure element with
+  Nothing -> Nothing
+  Just configuration -> do
+    adapters = editorAdapters configuration
+    if(length adapters > 0) then Just (configuration, adapters!0) else Nothing
+
+navigateToSubstructureAction :: Resource -> <Proc> ()
+navigateToSubstructureAction element = do
+ match (syncRead (\x -> possibleSubstructureEditor element)) with
+   Nothing -> ()
+   Just (configuration,editor) -> openEditor editor configuration
+                
\ No newline at end of file
diff --git a/bundles/org.simantics.modeling/scl/Simantics/Workbench.scl b/bundles/org.simantics.modeling/scl/Simantics/Workbench.scl
new file mode 100644 (file)
index 0000000..2506124
--- /dev/null
@@ -0,0 +1,21 @@
+import "Simantics/DB"
+
+importJava "org.simantics.ui.workbench.editor.EditorAdapter" where
+    data EditorAdapter
+    openEditor :: EditorAdapter -> a -> <Proc> ()
+
+importJava "org.simantics.ui.workbench.editor.EditorRegistry" where
+
+    @private
+    @JavaName getInstance
+    getEditorRegistryInstance :: IEditorRegistry
+
+importJava "org.simantics.ui.workbench.editor.IEditorRegistry" where
+    data IEditorRegistry
+    
+    @private
+    @JavaName getAdaptersFor
+    editorAdapters_ :: IEditorRegistry -> a -> <ReadGraph> Vector EditorAdapter
+
+editorAdapters :: a -> <ReadGraph> [EditorAdapter]
+editorAdapters object = vectorToList $ editorAdapters_ getEditorRegistryInstance object
index 78125828c58cc6628c572744d9394b56785698c2..3b4806c7ce927a78b46bdc60f8931b3bb6db535d 100644 (file)
@@ -101,6 +101,7 @@ import org.simantics.db.layer0.request.IsLinkedTo;
 import org.simantics.db.layer0.request.PossibleModel;
 import org.simantics.db.layer0.util.ClipboardUtils;
 import org.simantics.db.layer0.util.DraftStatusBean;
+import org.simantics.db.layer0.util.ExternalDownloadBean;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;
 import org.simantics.db.layer0.util.PasteEventHandler;
@@ -1497,6 +1498,11 @@ public class ModelingUtils {
                
             TransferableGraph1 tg = ClipboardUtils.accept(processor, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
             monitor.worked(95);
+            
+            Variant edb = tg.extensions.get(ExternalDownloadBean.EXTENSION_KEY);
+            if(edb != null) {
+               metadata.put(ExternalDownloadBean.EXTENSION_KEY, edb);
+            }
 
             monitor.setTaskName("Writing transferable graph...");
             DataContainers.writeFile(location, new DataContainer(
index 33d7f06290e109e69fdc4ceff7afb00c8b7cd00a..358d50fb4b4c9ac6f5f673ac3836bddf6f5ee383 100644 (file)
@@ -1,10 +1,28 @@
 package org.simantics.modeling;
 
+import java.awt.Dimension;
+import java.awt.RenderingHints;
+import java.awt.RenderingHints.Key;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
 import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.diagram.elements.DiagramNodeUtil;
@@ -20,7 +38,10 @@ import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
 import org.simantics.g2d.utils.CanvasUtils;
 import org.simantics.scenegraph.ParentNode;
 import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.G2DRenderingHints;
 import org.simantics.scenegraph.g2d.G2DSceneGraph;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.g2d.IG2DNodeVisitor;
 import org.simantics.scenegraph.g2d.events.command.Commands;
 import org.simantics.scenegraph.g2d.nodes.BackgroundNode;
 import org.simantics.scenegraph.g2d.nodes.BoundsNode;
@@ -28,13 +49,23 @@ import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
 import org.simantics.scenegraph.g2d.nodes.DataNode;
 import org.simantics.scenegraph.g2d.nodes.DecorationSVGNode;
 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
+import org.simantics.scenegraph.g2d.nodes.SVGNode;
 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
 import org.simantics.scenegraph.utils.NodeUtil;
 import org.simantics.trend.impl.ItemNode;
 import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 
 public class SCLScenegraph {
-       
+
+       private static final Logger LOGGER = LoggerFactory.getLogger(SCLScenegraph.class);
+
        public static ICanvasSceneGraphProvider getICanvasSceneGraphProvider(Resource model, Resource diagram, String diagramRVI) throws DatabaseException, InterruptedException {
                ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(model, diagram, diagramRVI);
                return provider;
@@ -44,13 +75,6 @@ public class SCLScenegraph {
                provider.dispose();
        }
        
-       //public static Resource getDiagramRuntime(Resource ) 
-       
-       
-//     public static String getNodeTransform(ICanvasContext ctx, String name) throws DatabaseException, InterruptedException {
-//             return getNodeTransform(ctx, name);
-//     }
-       
        public static String getNodeTransform(ICanvasContext ctx, String name) {
                
                Set<TextNode> texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
@@ -234,7 +258,7 @@ public class SCLScenegraph {
         }
     }
     
-     public static boolean copyPaste (final ICanvasContext source_ctx, final ICanvasContext target_ctx, List<Resource> modules) throws DatabaseException {
+    public static boolean copyPaste (final ICanvasContext source_ctx, final ICanvasContext target_ctx, List<Resource> modules) throws DatabaseException {
        
        IDiagram idiagram = source_ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);
 
@@ -286,5 +310,259 @@ public class SCLScenegraph {
                return true;
     }
 
+       static class Generator extends SVGGraphics2D {
+
+               int elemLevel = 0;
+               String newElementId = null;
+               ArrayList<Element> elements = new ArrayList<Element>();
+
+               public static final String svgNS = "http://www.w3.org/2000/svg";
+
+               public Generator(SVGGeneratorContext ctx, boolean joku) {
+                       super(ctx, joku);
+               }
+
+               public Generator(Document document) {
+                       super(document);
+               }
+
+               @Override
+               public Element getRoot() {
+                       Element root = super.getRoot();
+                       for(Element e : elements) {
+                               root.appendChild(e);
+                       }
+                       return root;
+               }
+
+               @Override
+               public void setRenderingHint(Key arg0, Object arg1) {
+                       if(G2DRenderingHints.KEY_BEGIN_ELEMENT == arg0) {
+                               elemLevel++;
+                       }
+                       if(G2DRenderingHints.KEY_ELEMENT_ID == arg0) {
+                               if(arg1 != null)
+                                       newElementId = arg1.toString();
+                               else
+                                       newElementId = UUID.randomUUID().toString();
+                       }
+                       if(G2DRenderingHints.KEY_END_ELEMENT == arg0) {
+                               elemLevel--;
+                               if(elemLevel == 0) {
+                                       Element group = getDOMFactory().createElement(SVG_G_TAG);
+                                       //Element group = getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
+                                       group.setAttributeNS(null, "id", newElementId);
+                                       group.setAttributeNS(null, "class", arg1.toString());
+                                       getRoot(group);
+                                       elements.add(group);
+                               }
+                       }
+                       super.setRenderingHint(arg0, arg1);
+               }
+
+       }
+
+       public static Element renderSVGNode(IG2DNode node) {
+
+               // Get a DOMImplementation.
+               DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+
+               // Create an instance of org.w3c.dom.Document.
+               String svgNS = "http://www.w3.org/2000/svg";
+               Document document = domImpl.createDocument(svgNS, "svg", null);
+
+               SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
+               ctx.setComment(null);
+
+               // Create an instance of the SVG Generator.
+               SVGGraphics2D svgGenerator = new Generator(ctx, false);
+
+               try {
+
+                       svgGenerator.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+                       svgGenerator.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+                       svgGenerator.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+                       node.render(svgGenerator);
+
+               } catch (Throwable t) {
+                       LOGGER.error("Problems rendering scene graph to SVG", t);
+               }
+
+               return svgGenerator.getRoot();
+       }
+
+       public static String printSVGDocument(Element doce) {
+
+               StringBuilder result = new StringBuilder();
+
+               NodeList nl =  doce.getChildNodes();
+
+               for(int i=0;i<nl.getLength();i++) {
+
+                       ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+                       try {
+
+                               TransformerFactory tf = TransformerFactory.newInstance();
+                               Transformer transformer = tf.newTransformer();
+                               transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+                               transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
+                               transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+                               transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+                               transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+                               transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+                               transformer.transform(new DOMSource(nl.item(i)), 
+                                               new StreamResult(new OutputStreamWriter(os, "UTF-8")));
+
+                               os.flush();
+                               os.close();
+
+                       } catch (Throwable t) {
+                               LOGGER.error("Problems formatting SVGDocument to text.", t);
+                       }
+
+                       result.append(new String(os.toByteArray()));
+
+               }
+
+               return result.toString();
+
+       }
+
+       public static String renderSVG(ICanvasContext ctx) {
+
+               // Get a DOMImplementation.
+               DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+
+               // Create an instance of org.w3c.dom.Document.
+               String svgNS = "http://www.w3.org/2000/svg";
+               Document document = domImpl.createDocument(svgNS, "svg", null);
+
+               // Create an instance of the SVG Generator.
+               SVGGraphics2D svgGenerator = new Generator(document);
+
+               StringBuilder b = new StringBuilder();
+
+               try {
+
+                       G2DSceneGraph sg = ctx.getSceneGraph();
+                       G2DParentNode root = (G2DParentNode) sg.getRootNode();
+
+                       // rtree is the actual content of the diagram
+                       RTreeNode rtree = NodeUtil.getNearestChildByClass(root, RTreeNode.class);
+                       Rectangle2D rtreeBounds = NodeUtil.getLocalBounds(rtree);
+
+                       // nav is a node that has zooming functionalities
+                       NavigationNode nav = NodeUtil.getNearestChildByClass(root, NavigationNode.class);
+                       nav.setZoomEnabled(true);
+
+                       // fit view with the contents of rtreeBounds
+                       nav.zoomTo(rtreeBounds);
+
+                       // get the bounds of the content
+                       Rectangle2D content = NodeUtil.getLocalBounds(nav);
+
+                       svgGenerator.scale(3,3);
+
+                       // translate svgGenerator to the x and y coordinates of current content
+                       svgGenerator.translate(-1 * content.getX(), (-1 * content.getY()));
+
+                       Rectangle2D destination = new Rectangle2D.Double(0,0,1000,1000);
+                       double sx = destination.getWidth() / content.getWidth();
+                       double sy = destination.getHeight() / content.getHeight();
+                       double scale = sx < sy ? sx : sy;
+
+                       // Set svgCanvasSize to the given size parameters
+                       svgGenerator.setSVGCanvasSize(new Dimension((int)(scale * content.getWidth()), (int)(scale * content.getHeight())));
+                       svgGenerator.setClip(content);
+
+                       double trX = -1 * content.getX();
+                       double trY = -1 * content.getY();
+
+                       b.append("<svg width=\"100%\" height=\"100%\" stroke=\"black\"><g transform=\"translate(").append(trX).append(' ').append(trY).append(")\">");
+
+                       IG2DNodeVisitor visitor = new IG2DNodeVisitor() {
+
+                               int indent = 0;
+
+                               HashMap<IG2DNode,Integer> enters = new HashMap<>();
+
+                               @Override
+                               public void enter(IG2DNode node) {
+                                       indent++;
+                                       if(node instanceof ConnectionNode) {
+                                               Element doc = renderSVGNode((IG2DNode)node);
+                                               String svg = printSVGDocument(doc);
+                                               b.append(svg);
+                                       } else if (node instanceof SVGNode) {
+                                               SVGNode svg = (SVGNode)node;
+                                               b.append(svg.getSVGText());
+                                       } else if (node instanceof G2DParentNode) {
+                                               AffineTransform at = node.getTransform();
+                                               if(node instanceof SingleElementNode) {
+                                                       SingleElementNode sen = (SingleElementNode)node;
+                                                       if(sen.getKey() != null) {
+                                                               String key = sen.getKey().toString();
+                                                               b.append("\n<g class=\"definedElement\" id=\"" + key + "\">");
+                                                       }
+                                               }
+                                               if(!at.isIdentity()) {
+                                                       if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
+                                                               String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
+                                                               b.append("\n<g transform=\"" + m + "\">");
+                                                       } else {
+                                                               double[] ds = new double[6];
+                                                               at.getMatrix(ds);
+                                                               String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
+                                                               b.append("\n<g transform=\"" + m + "\">");
+                                                       }
+                                               }
+                                       }
+
+                                       enters.put(node, b.length());
+
+                               }
+
+                               @Override
+                               public void leave(IG2DNode node) {
+                                       if(node instanceof ConnectionNode || node instanceof SVGNode) {
+                                               // We are done
+                                       } else if (node instanceof G2DParentNode) {
+                                               AffineTransform at = node.getTransform();
+                                               if(!at.isIdentity()) {
+                                                       b.append("</g>");
+                                               }
+                                               if(node instanceof SingleElementNode) {
+                                                       SingleElementNode sen = (SingleElementNode)node;
+                                                       if(sen.getKey() != null) {
+                                                               int enterLength = enters.get(node);
+                                                               if(b.length() == enterLength) {
+                                                                       Element doc = renderSVGNode((IG2DNode)node);
+                                                                       String svg = printSVGDocument(doc);
+                                                                       b.append(svg);
+                                                               }
+                                                               b.append("</g>");
+                                                       }
+                                               }
+                                       }
+                                       indent --;
+                               }
+
+                       };
+                       sg.accept(visitor);
+
+               } catch (Throwable t) {
+                       LOGGER.error("Problems rendering canvas context to SVG", t);
+               }
+
+               b.append("</g></svg>");
+               //System.err.println(" == FINAL RESULT == ");
+               //System.err.println(b);
+               return b.toString();
+
+       }
+
 
 }
\ No newline at end of file
index f090be06c6bc1d1335a28d53a8b1b673820b2674..3fc0d46fa58cb34e2f5c77f39696b816cc244f67 100644 (file)
@@ -10,9 +10,12 @@ import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
 
 public class Activator implements BundleActivator {
 
+    private static BundleContext context;
+    
     @SuppressWarnings({ "rawtypes", "unchecked" })
     @Override
     public void start(BundleContext context) throws Exception {
+        Activator.context = context;
         Hashtable properties = new Hashtable();
         
         context.registerService(ModuleSourceRepository.class, OntologyModuleSourceRepository.INSTANCE, properties);
@@ -23,5 +26,7 @@ public class Activator implements BundleActivator {
     public void stop(BundleContext context) throws Exception {
     }
 
-    
+    public static BundleContext getContext() {
+        return context;
+    }
 }
index be13d8cf8ebd42c9a7c65084966f8eeea0856d54..994aa1ab13feb132f6a9ce5ebaa5270c01bf6582 100644 (file)
@@ -11,9 +11,8 @@
  *******************************************************************************/
 package org.simantics.modeling.mapping;
 
-import gnu.trove.map.hash.THashMap;
-
 import java.util.Map;
+import java.util.function.BiFunction;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
@@ -33,7 +32,8 @@ import org.simantics.diagram.synchronization.graph.CopyAdvisorUtil;
 import org.simantics.diagram.synchronization.graph.GraphCopyAdvisor;
 import org.simantics.diagram.synchronization.graph.GraphSynchronizationHints;
 import org.simantics.layer0.Layer0;
-import org.simantics.utils.datastructures.BinaryFunction;
+
+import gnu.trove.map.hash.THashMap;
 
 /**
  * @author Tuukka Lehtonen
@@ -48,10 +48,10 @@ public class ElementCopyAdvisor extends GraphCopyAdvisor {
      * Diagram mapping will have problems and potentially break the
      * configuration if the type is not the same as in the source.
      */
-    BinaryFunction<StatementEvaluation, ReadGraph, Statement> statementAdvisor =
-            new BinaryFunction<StatementEvaluation, ReadGraph, Statement>() {
+    BiFunction<ReadGraph, Statement, StatementEvaluation> statementAdvisor =
+            new BiFunction<ReadGraph, Statement, StatementEvaluation>() {
         @Override
-        public StatementEvaluation call(ReadGraph graph, Statement stm) {
+        public StatementEvaluation apply(ReadGraph graph, Statement stm) {
             if (DIA.HasFlagType.equals(stm.getPredicate()))
                 return StatementEvaluation.INCLUDE;
             if (G2D.HasFontStyle.equals(stm.getPredicate()))
index 10eeb6ac6aacce7255c510b848de59a4e55416b6..dfea839318d2c33415dd454c30a60980e9e55c5f 100644 (file)
@@ -29,10 +29,14 @@ import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.runtime.SCLContext;
 import org.simantics.scl.runtime.function.Function1;
 import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 public class CompileSCLMonitorRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {
-    
+
+    private static Logger LOGGER = LoggerFactory.getLogger(CompileSCLMonitorRequest.class);
+
     protected static Name BROWSE = Name.create("Simantics/Variables", "browse");
     protected static Name VALUE = Name.create("Simantics/Variables", "value");
     
@@ -72,10 +76,8 @@ public class CompileSCLMonitorRequest extends AbstractExpressionCompilationReque
             sclContext.put("graph", graph);
             return exp.apply(context.getParent(graph));
         } catch (DatabaseException e) {
-            e.printStackTrace();
             throw (DatabaseException)e;
         } catch (Throwable t) {
-            t.printStackTrace();
             throw new DatabaseException(t);
         } finally {
             sclContext.put("graph", oldGraph);
@@ -98,7 +100,7 @@ public class CompileSCLMonitorRequest extends AbstractExpressionCompilationReque
             try {
                 return Environments.getType(context.runtimeEnvironment.getEnvironment(), valueType);
             } catch (SCLExpressionCompilationException e) {
-                e.printStackTrace();
+                LOGGER.warn("getExpectedType failed for valueType: " + valueType, e);
             }
         }
         return super.getExpectedType(graph, context);
index 07af09e557109046575ee8556abf20c5cca6ec84..c75f7a941a55f76c2bd668b0646a5fa76f40d826 100644 (file)
@@ -15,11 +15,14 @@ import org.simantics.db.procedure.SyncListener;
 import org.simantics.db.request.Read;
 import org.simantics.layer0.Layer0;
 import org.simantics.modeling.ModelingUtils;
+import org.simantics.modeling.internal.Activator;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.module.repository.UpdateListener.Observable;
 import org.simantics.scl.compiler.source.ModuleSource;
 import org.simantics.scl.compiler.source.StringModuleSource;
 import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
+import org.simantics.scl.osgi.internal.OsgiJavaReferenceValidatorFactory;
 import org.simantics.scl.runtime.SCLContext;
 import org.simantics.scl.runtime.tuple.Tuple0;
 import org.simantics.structural2.utils.StructuralUtils;
@@ -29,6 +32,8 @@ import gnu.trove.set.hash.THashSet;
 
 public enum GraphModuleSourceRepository implements ModuleSourceRepository {
     INSTANCE;
+    
+    private static final OsgiJavaReferenceValidatorFactory REFERENCE_VALIDATOR_FACTORY = new OsgiJavaReferenceValidatorFactory(Activator.getContext().getBundle());
 
     @Override
     public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) {
@@ -123,6 +128,11 @@ public enum GraphModuleSourceRepository implements ModuleSourceRepository {
                 e.printStackTrace();
             }
         }
+        
+        @Override
+        public JavaReferenceValidatorFactory getJavaReferenceValidatorFactory() {
+            return REFERENCE_VALIDATOR_FACTORY;
+        }
     }
 
     static class ReadModuleSource extends UnaryRead<String, ModuleSource> {
index 17aba97ea1e9165c4b50222e99d10adc63fee5f9..1c8c91927fc9cc525f966555fbbe1515c6ae012d 100644 (file)
@@ -312,4 +312,9 @@ public class OntologyModule extends LazyModule {
     public String toString() {
         return new StringBuilder().append("OntologyModule ").append(getName()).toString();
     }
+
+    @Override
+    public ClassLoader getParentClassLoader() {
+        return getClass().getClassLoader();
+    }
 }
index eafb6ec76ba847404f9b0cc19d1c6a9714fa9d4e..9509da624ea45451dc49d3225679c7a5ba008b82 100644 (file)
Binary files a/bundles/org.simantics.platform.ui.ontology/graph.tg and b/bundles/org.simantics.platform.ui.ontology/graph.tg differ
index 7fedc55d11ae8a5713f83e6e5315dbc192cb4e7b..bb2ba5c2c411310fb1971e6609dce41fcf2f814d 100644 (file)
@@ -14,8 +14,6 @@ package org.simantics.project;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -188,22 +186,25 @@ public class ProjectFeatures {
             return false;
         }
 
-        private Collection<IProjectFeatureExtension> sortTopologically(Collection<IProjectFeatureExtension> toSort) {
-            ArrayList<IProjectFeatureExtension> sorted = new ArrayList<IProjectFeatureExtension>(toSort);
-            Collections.sort(sorted, new Comparator<IProjectFeatureExtension>() {
-                Set<IProjectFeatureExtension> visited = new HashSet<IProjectFeatureExtension>();
-                @Override
-                public int compare(IProjectFeatureExtension e1, IProjectFeatureExtension e2) {
-                    visited.clear();
-                    if (deepRequires(visited, e1, e2))
-                        return 1;
-                    visited.clear();
-                    if (deepRequires(visited, e2, e1))
-                        return -1;
-                    return 0;
+        private void requiresDFS(IProjectFeatureExtension ext, ArrayList<IProjectFeatureExtension> result, Set<IProjectFeatureExtension> visited) {
+            if(visited.add(ext)) {
+                Set<IProjectFeatureExtension> reqs = required.getValues(ext);
+                if(reqs != null) {
+                    for(IProjectFeatureExtension req : reqs) {
+                        requiresDFS(req, result, visited);
+                    }
                 }
-            });
-            return sorted;
+                result.add(ext);
+            }
+        }
+
+        private Collection<IProjectFeatureExtension> sortTopologically(Collection<IProjectFeatureExtension> toSort) {
+            ArrayList<IProjectFeatureExtension> result = new ArrayList<>();
+            Set<IProjectFeatureExtension> visited = new HashSet<>();
+            for(IProjectFeatureExtension ext : toSort) {
+                requiresDFS(ext, result, visited);
+            }
+            return result;
         }
 
         private Collection<IProjectFeatureExtension> requiredExtensions(IProjectFeatureExtension[] allExtensions, Collection<IProjectFeatureExtension> includedExtensions) throws ProjectException {
@@ -234,7 +235,8 @@ public class ProjectFeatures {
                             if (injectionTargetExt != null) {
                                 changed = true;
                                 includedProjectFeatureIds.add(ext.getId());
-                                result.add(ext);
+                                if(!result.contains(ext))
+                                    result.add(ext);
                                 required.add(injectionTargetExt, ext);
                             }
                         }
index e861bc09dc47e81f3b1857889c835db091837048..b07304ed1ce3b8d39af3c5c8d06b1dd5cc6ccf3e 100644 (file)
@@ -94,7 +94,7 @@ public class ProjectFeatureRegistry implements IProjectFeatureRegistry, IExtensi
                 String description = StringUtils.safeString(el.getAttribute("description"));
                 boolean published = "true".equalsIgnoreCase(el.getAttribute("published"));
                 Collection<ProjectFeatureReference> requires = readProjectFeatureReferenceCollection(el, "requires");
-                Collection<InjectedDependency> injections = readInjectedDependencies(el);
+                Collection<InjectedDependency> injections = readInjectedDependencies(el, id);
                 Collection<GroupReference> installGroups = readGroupReferenceCollection(el, "installGroup");
 
                 ProjectFeatureExtension ext = new ProjectFeatureExtension(el, id, label, description, published, requires, injections, installGroups);
@@ -111,19 +111,17 @@ public class ProjectFeatureRegistry implements IProjectFeatureRegistry, IExtensi
         this.extensions = newExtensions.toArray(new IProjectFeatureExtension[newExtensions.size()]);
     }
 
-    private Collection<InjectedDependency> readInjectedDependencies(IConfigurationElement element) {
+    private Collection<InjectedDependency> readInjectedDependencies(IConfigurationElement element, String id) {
         Collection<InjectedDependency> result = new ArrayList<InjectedDependency>();
 
         for (IConfigurationElement child : element.getChildren(INJECT_DEPENDENCY)) {
-            String id = StringUtils.safeString(child.getAttribute("id"));
-            if (id.isEmpty())
-                // Invalid extension
-                return null;
-
             String targetId = StringUtils.safeString(child.getAttribute("targetId"));
             if (targetId.isEmpty())
                 // Invalid extension
                 return null;
+            
+            result.add(new InjectedDependency(new ProjectFeatureReference(id, false), new ProjectFeatureReference(targetId, false)));
+            
         }
 
         return result;
index 085f5cd15d011894f25fd92ea36c5eb40ac531fa..ba17d92ec4ef48bc80aeb16ba25d456667ae0b4c 100644 (file)
@@ -13,7 +13,8 @@ Require-Bundle: org.simantics.db.layer0;bundle-version="1.1.0",
  org.simantics.basicexpression;bundle-version="1.1.0",
  org.simantics.scenegraph;bundle-version="1.1.1",
  org.eclipse.core.runtime;bundle-version="3.6.0",
- org.simantics.diagram.ontology;bundle-version="1.1.1"
+ org.simantics.diagram.ontology;bundle-version="1.1.1",
+ org.simantics.db.common
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.simantics.scenegraph.profile.impl.Activator
 Import-Package: org.simantics
diff --git a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/request/AvailableProfiles.java b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/request/AvailableProfiles.java
new file mode 100644 (file)
index 0000000..3c3276a
--- /dev/null
@@ -0,0 +1,51 @@
+package org.simantics.scenegraph.profile.request;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.NamedResource;
+import org.simantics.db.common.request.ResourceRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.adapter.Instances;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.layer0.Layer0;
+
+public class AvailableProfiles extends ResourceRead<List<NamedResource>>{
+
+       protected AvailableProfiles(Resource runtimeDiagram) {
+               super(runtimeDiagram);
+       }
+
+       @Override
+       public List<NamedResource> perform(ReadGraph graph) throws DatabaseException {
+               
+                 Layer0 L0 = Layer0.getInstance(graph);
+               DiagramResource DIA = DiagramResource.getInstance(graph);
+
+               String indexURI = graph.getPossibleRelatedValue(resource, DIA.RuntimeDiagram_HasModelURI);
+               if (indexURI == null)
+                   return Collections.emptyList();
+
+               Resource index = graph.getPossibleResource(indexURI);
+               if (index == null)
+                   return Collections.emptyList();
+
+               Instances query = graph.adapt(DIA.Profile, Instances.class);
+
+               ArrayList<NamedResource> result = new ArrayList<>();
+               for(Resource profile : query.find(graph, index)) {
+                       if(!graph.hasStatement(profile, L0.Abstract)) {
+                               String name = graph.getRelatedValue(profile, L0.HasName, Bindings.STRING);
+                               result.add(new NamedResource(name, profile));
+                       }
+               }
+               
+               return result;
+               
+       }
+
+}
\ No newline at end of file
index 762ee12bdd0cbf7c10c5db51fda81c7953a64e03..5686024b0c702176352e73d34e0475b84903a5e2 100644 (file)
@@ -13,9 +13,11 @@ package org.simantics.scenegraph.profile.request;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
+import org.simantics.db.common.NamedResource;
 import org.simantics.db.common.request.ResourceRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.diagram.stubs.DiagramResource;
@@ -35,8 +37,14 @@ public class RuntimeProfileActiveEntryResources extends ResourceRead<Collection<
 
         ArrayList<Resource> result = new ArrayList<Resource>();
         Resource activeProfile = graph.getPossibleObject(resource, DIA.RuntimeDiagram_HasRuntimeProfile);
-        if (activeProfile == null)
-            return result;
+        if (activeProfile == null) {
+               
+               List<NamedResource> available = graph.syncRequest(new AvailableProfiles(resource));
+               if(available.size() != 1) return result;
+               
+               activeProfile = available.iterator().next().getResource();
+            
+        }
 
         Resource rootEntries = graph.getPossibleObject(activeProfile, DIA.HasEntries);
         if (rootEntries == null)
index 08cac2fb83d21ea60e7a141fe65520cea4cb5aa3..f291d07b198152c75dd522aa9893857dab7d00e7 100644 (file)
@@ -357,7 +357,7 @@ public class AttributeDialog extends Dialog implements ISelectionChangedListener
                 updateHeader(cell, ((Header) elem).name);
             } else if (elem instanceof Class<?>) {
                 Class<?> clazz = (Class<?>) elem;
-                updateHeader(cell, clazz.getSimpleName());
+                updateHeader(cell, clazz.getSimpleName() + " (" + clazz.getPackage().getName() + ")");
             }
         }
 
index cf4fe0b308e1d246ea719a06fc9fb30dea749076..b39d7a0582167f7b6222a550b44c4d5954769ca9 100644 (file)
@@ -395,5 +395,10 @@ public abstract class G2DNode extends Node implements IG2DNode {
         if (rootPane != null)
             rootPane.setCursor(cursor);
     }
+    
+    public void accept(IG2DNodeVisitor visitor) {
+        visitor.enter(this);
+        visitor.leave(this);
+    }
 
 }
index 231b616e2a0a1a8f09497ce12941a6a562782a4c..838eb893e52b392b78a8796adf4e6e10e17fd7cc 100644 (file)
@@ -122,6 +122,17 @@ public class G2DParentNode extends ParentNode<IG2DNode> implements IG2DNode, Ini
             g2d.setTransform(ot);
     }
 
+    @Override
+    public void accept(IG2DNodeVisitor visitor) {
+        visitor.enter(this);
+        for (IG2DNode node : getSortedNodes()) {
+            if (node.validate()) {
+                node.accept(visitor);
+            }
+        }
+        visitor.leave(this);
+    }
+
     /**
      * Return the IDs of the children of this node in ascending Z order. This
      * method will always allocate a new result list and sort it. To get the IDs
index 00c7a6d0c8c516ead3e619f6edc8b8bb0070c9db..0f1803e2d64ee6d27d74695cab015a62fa658b54 100644 (file)
@@ -12,8 +12,8 @@
 package org.simantics.scenegraph.g2d;
 
 import java.awt.Component;
-import java.awt.RenderingHints.Key;
 import java.awt.geom.Rectangle2D;
+import java.util.Map;
 
 /**
  * @author Tuukka Lehtonen
@@ -21,6 +21,32 @@ import java.awt.geom.Rectangle2D;
  */
 public final class G2DRenderingHints {
 
+    public static final Key KEY_BEGIN_ELEMENT = new G2DRenderingHints.Key(0);
+    public static final Key KEY_END_ELEMENT = new G2DRenderingHints.Key(1);
+    public static final Key KEY_ELEMENT_ID = new G2DRenderingHints.Key(2);
+
+    public static class Key extends java.awt.RenderingHints.Key {
+
+        public Key(int privateKey) {
+            super(privateKey);    
+        }
+    
+        @Override
+        public boolean isCompatibleValue(Object val) {
+            switch (intKey()) {
+                case 0:
+                    return val == null || val instanceof String 
+                            || val instanceof Map;
+                case 1:
+                    return val == null || val instanceof Object;
+                case 2:
+                    return val == null || val instanceof Object;
+                default:
+                    throw new RuntimeException("Not possible!");
+            }
+        }
+    }
+       
     /**
      * A rendering hint for storing the boundaries of the control area within a
      * Graphics2D instance.
index 0afebc2db387857a305a8458001755c28766e973..e181d59ff02d45305da28dbbac3cb7802be5b002 100644 (file)
@@ -71,6 +71,14 @@ public interface IG2DNode extends INode, IEventHandler {
      */
     public void render(Graphics2D g2d);
 
+    /**
+     * Visit the IG2DNode substructure of this node using the provided visitor.
+     * 
+     * @param visitor the visitor to use
+     * @since 1.29.0
+     */
+    public void accept(IG2DNodeVisitor visitor);
+
     /**
      * Mark the scene graph to be repainted in its current rendering context (UI
      * component) as soon as is appropriate for the backend system.
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java
new file mode 100644 (file)
index 0000000..2f52117
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.g2d;
+
+/**
+ * @author Antti Villberg
+ * @since 1.29.0
+ */
+public interface IG2DNodeVisitor {
+
+       public void enter(IG2DNode node);
+       public void leave(IG2DNode node);
+
+}
index 598dab9fefe266a62b12cfaf3946fcbc6907a8c7..ec0a4fe5f1a35182901cdb311c9fe7186356b83f 100644 (file)
@@ -75,8 +75,8 @@ public class NodeEventHandler implements IEventHandler {
 
         void getTreePath(INode node, ArrayList<INode> result) {
              result.clear();
-             for (INode parent = node.getParent(); parent != null; parent = parent.getParent())
-                 result.add(parent);
+             for (; node != null; node = node.getParent())
+                 result.add(node);
         }
 
         void notSameGraph(INode o1, INode o2) {
@@ -94,19 +94,15 @@ public class NodeEventHandler implements IEventHandler {
             ArrayList<INode> path1 = tmp.path1;
             ArrayList<INode> path2 = tmp.path2;
 
-            // Get path to root node for both nodes
-            INode o1 = (INode) e1;
-            INode o2 = (INode) e2;
-            getTreePath(o1, path1);
-            getTreePath(o2, path2);
+            try {
+               // Get path to root node for both nodes
+               getTreePath((INode) e1, path1);
+               getTreePath((INode) e2, path2);
 
-            // Sanity checks: nodes part of same scene graph
-            INode root1 = path1.isEmpty() ? o1 : path1.get(path1.size() - 1);
-            INode root2 = path2.isEmpty() ? o2 : path2.get(path2.size() - 1);
-            if (root1 != root2)
-                notSameGraph(o1, o2);
+               // Sanity checks: nodes part of same scene graph
+               if (path1.get(path1.size() - 1) != path2.get(path2.size() - 1))
+                       notSameGraph((INode)e1, (INode)e2);
 
-            try {
                 // Find first non-matching nodes in the paths starting from the root node
                 int i1 = path1.size() - 1;
                 int i2 = path2.size() - 1;
@@ -124,27 +120,31 @@ public class NodeEventHandler implements IEventHandler {
                 if (i2 < 0)
                     return Order.ASCENDING == order ? 1 : -1;
 
-                INode n1 = path1.get(i1);
-                INode n2 = path2.get(i2);
-                IG2DNode g1 = n1 instanceof IG2DNode ? (IG2DNode) n1 : null;
-                IG2DNode g2 = n2 instanceof IG2DNode ? (IG2DNode) n2 : null;
-                if (g1 != null && g2 != null) {
-                    int z1 = g1.getZIndex();
-                    int z2 = g2.getZIndex();
-                    int c = compare(z1, z2);
-                    return order == Order.ASCENDING ? c : -c;
-                }
-                // Can't sort non-IG2DNodes.
-                return 0;
+                return compare(path1.get(i1), path2.get(i2));
             } finally {
                 // Don't hold on to objects unnecessarily
                 path1.clear();
                 path2.clear();
             }
         }
-
-        private int compare(int v1, int v2) {
-            return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0);
+        
+        private int compare(INode n1, INode n2) {
+               if(n1 instanceof IG2DNode) {
+                       if(n2 instanceof IG2DNode) {
+                       int z1 = ((IG2DNode)n1).getZIndex();
+                       int z2 = ((IG2DNode)n2).getZIndex();
+                       int c = Integer.compare(z1, z2);
+                       return order == Order.ASCENDING ? c : -c;
+                       }
+                       else
+                               return -1; // sort IG2DNodes before non-IG2DNodes
+            }
+               else {
+                       if(n2 instanceof IG2DNode)
+                               return 1;
+                       else
+                               return 0; // all non-IG2DNodes are equal in comparison
+               }
         }
     };
 
index a83ca52647719d4dd3d4001605f9a3086336bdb9..d4543c6d110546c08cf8709f94f3af81d9501810 100644 (file)
@@ -13,11 +13,13 @@ package org.simantics.scenegraph.g2d.nodes;
 
 import java.awt.Color;
 import java.awt.Composite;
+import java.awt.Graphics2D;
 import java.awt.Stroke;
 import java.awt.geom.Point2D;
 
 import org.simantics.diagram.connection.RouteGraph;
 import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.G2DRenderingHints;
 import org.simantics.scenegraph.g2d.IG2DNode;
 import org.simantics.scenegraph.g2d.events.MouseEvent;
 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
@@ -150,4 +152,14 @@ public class ConnectionNode extends SingleElementNode implements InitValueSuppor
         return false;
     }
 
+    @Override
+    public void beforeRender(Graphics2D g) {
+        g.setRenderingHint(G2DRenderingHints.KEY_BEGIN_ELEMENT, "connection");
+    }
+    
+    @Override
+    public void afterRender(Graphics2D g) {
+        g.setRenderingHint(G2DRenderingHints.KEY_END_ELEMENT, "connection");
+    }
+    
 }
index 97de387f8b0fce3bfcf2728a19b11cb9327b7894..cdd6a26458f578d4b30fbe3e5b8099a6191f6550 100644 (file)
@@ -208,51 +208,59 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
         if (data == null)
             return null;
 
+        SVGUniverse univ = SVGCache.getSVGUniverse();
         try {
-               SVGUniverse univ = SVGCache.getSVGUniverse();
-               synchronized(univ) {
-                       // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
-                       byte[] dataBytes = data.getBytes("UTF-8");
-                       dataHash = digest(dataBytes, assignments);
-                       if (diagramCache != null)
-                               univ.decRefCount(diagramCache.getXMLBase());
-                       URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), dataHash);
-                       diagramCache = univ.getDiagram(uri, false);
-                       if (diagramCache != null) {
-                               if (diagramCache.getRoot() == null) {
-                                       diagramCache = univ.getDiagram(univ.loadSVG(BROKEN_SVG_DATA), false);
-                                       dataHash = "broken";
-                               } else if (diagramCache.getRoot().getBoundingBox().isEmpty()) {
-                                       diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
-                                       dataHash = "empty";
-                               } else {
-                                       for(SVGNodeAssignment ass : assignments) {
-                                               SVGElement e = diagramCache.getElement(ass.elementId);
-                                               if(e != null) {
-                                                       if("$text".equals(ass.attributeNameOrId)) {
-                                                               Tspan t = (Tspan)e;
-                                                               t.setText(ass.value);
-                                                               Text text = (Text)t.getParent();
-                                                               text.rebuild();
-                                                       } else {
-                                                               e.setAttribute(ass.attributeNameOrId, AnimationElement.AT_AUTO, ass.value);
-                                                       }
-                                               }
-                                       }
-                                       if(!assignments.isEmpty())
-                                               diagramCache.updateTime(0);
-                               }
-                       }
-                       documentCache = data;
-                       if (diagramCache != null) {
-                               setBounds((Rectangle2D) diagramCache.getRoot().getBoundingBox().clone());
-                               univ.incRefCount(diagramCache.getXMLBase());
-                       } else {
-                               setBounds(new Rectangle2D.Double());
-                       }
-               }
+            Rectangle2D bbox = null;
+            synchronized (univ) {
+                // Relinquish reference to current element
+                if (diagramCache != null) {
+                    univ.decRefCount(diagramCache.getXMLBase());
+                    diagramCache = null;
+                }
+
+                // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
+                byte[] dataBytes = data.getBytes("UTF-8");
+                dataHash = digest(dataBytes, assignments);
+                URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), dataHash);
+                diagramCache = univ.getDiagram(uri, false);
+
+                if (diagramCache != null) {
+                    univ.incRefCount(diagramCache.getXMLBase());
+
+                    if (diagramCache.getRoot() == null) {
+                        univ.decRefCount(diagramCache.getXMLBase());
+                        diagramCache = univ.getDiagram(univ.loadSVG(BROKEN_SVG_DATA), false);
+                        dataHash = "broken";
+                        univ.incRefCount(diagramCache.getXMLBase());
+                        bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+                    } else {
+                        bbox = diagramCache.getRoot().getBoundingBox();
+                        if (bbox.isEmpty()) {
+                            univ.decRefCount(diagramCache.getXMLBase());
+                            diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
+                            dataHash = "empty";
+                            univ.incRefCount(diagramCache.getXMLBase());
+                            bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+                        } else {
+                            if (applyAssignments(diagramCache, assignments)) {
+                                bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+                            } else {
+                                bbox = (Rectangle2D) bbox.clone();
+                            }
+                        }
+                    }
+                } else {
+                    bbox = new Rectangle2D.Double();
+                }
+            }
+
+            documentCache = data;
+            setBounds(bbox);
         } catch (SVGException e) {
-            setBounds((Rectangle2D) diagramCache.getViewRect().clone());
+            // This can only occur if diagramCache != null.
+            setBounds(diagramCache.getViewRect(new Rectangle2D.Double()));
+            univ.decRefCount(diagramCache.getXMLBase());
+            diagramCache = null;
         } catch (IOException e) {
             diagramCache = null;
         }
@@ -260,8 +268,34 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
         return dataHash;
     }
 
+    private static boolean applyAssignments(SVGDiagram diagram, List<SVGNodeAssignment> assignments) throws SVGException {
+        if (assignments.isEmpty())
+            return false;
+        boolean changed = false;
+        for (SVGNodeAssignment ass : assignments) {
+            SVGElement e = diagram.getElement(ass.elementId);
+            if (e != null) {
+                if ("$text".equals(ass.attributeNameOrId)) {
+                    if (e instanceof Tspan) {
+                        Tspan t = (Tspan) e;
+                        t.setText(ass.value);
+                        SVGElement parent = t.getParent();
+                        if (parent instanceof Text)
+                            ((Text) parent).rebuild();
+                        changed = true;
+                    }
+                } else {
+                    e.setAttribute(ass.attributeNameOrId, AnimationElement.AT_AUTO, ass.value);
+                    changed = true;
+                }
+            }
+        }
+        diagram.updateTime(0);
+        return changed;
+    }
+
     public static Rectangle2D getBounds(String data) {
-       return getBounds(data, null);
+        return getBounds(data, null);
     }
 
     public static Rectangle2D getBounds(String data, List<SVGNodeAssignment> assignments) {
@@ -301,7 +335,7 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
             }
             return rect;
         } catch (SVGException e) {
-            return ((Rectangle2D) diagramCache.getViewRect().clone());
+            return diagramCache.getViewRect(new Rectangle2D.Double());
         } catch(IOException e) {
         }
         return null;
@@ -330,13 +364,13 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
                 URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), digest);
                 diagramCache = univ.getDiagram(uri, false);
                 if (diagramCache != null) {
-                       SVGRoot root = diagramCache.getRoot(); 
+                    SVGRoot root = diagramCache.getRoot(); 
                     if (root == null) return new Rectangle2D.Double();
                     return (Rectangle2D)root.getBoundingBox().clone();
                 }
             }
         } catch (SVGException e) {
-            return ((Rectangle2D) diagramCache.getViewRect().clone());
+            return diagramCache.getViewRect(new Rectangle2D.Double());
         } catch(IOException e) {
         }
         return null;
@@ -444,4 +478,11 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
                this.setTransform(new AffineTransform(data));
        }
        
+       public String getSVGText() {
+               String ret = data.replace("<svg", "<g").replaceAll("svg>", "g>");
+               //return diagramCache.toString();
+               //return data.replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"><svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\"", "<g").replaceAll("svg>", "/g>");
+               return ret;
+       }
+       
 }
index 00ca6b8663f59c984097508f9cc9a5dba1491fc5..beee2538a534092c9f32c79577d9559b3851e3d9 100644 (file)
@@ -17,6 +17,7 @@ import java.awt.Graphics2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import org.simantics.scenegraph.g2d.G2DRenderingHints;
 import org.simantics.scenegraph.g2d.IG2DNode;
 import org.simantics.scenegraph.g2d.events.EventTypes;
 import org.simantics.scenegraph.g2d.events.MouseEvent;
@@ -32,6 +33,15 @@ public class SingleElementNode extends TransformNode implements InitValueSupport
     protected Composite composite;
     protected Boolean visible = Boolean.TRUE;
     protected Boolean hidden = Boolean.FALSE;
+    private transient Object key;
+
+    public void setKey(Object key) {
+        this.key = key;
+    }
+
+    public Object getKey() {
+        return key;
+    }
 
     public void setTransferableProvider(TransferableProvider transferableProvider) {
         if (transferableProvider != this.transferableProvider) {
@@ -169,4 +179,12 @@ public class SingleElementNode extends TransformNode implements InitValueSupport
         return EventTypes.MouseDragBeginMask;
     }
 
+    public void beforeRender(Graphics2D g) {
+        g.setRenderingHint(G2DRenderingHints.KEY_BEGIN_ELEMENT, "definedElement");
+    }
+
+    public void afterRender(Graphics2D g) {
+        g.setRenderingHint(G2DRenderingHints.KEY_END_ELEMENT, "definedElement");
+    }
+
 }
index 4cacc70f99bb2c23859095d7fa7df8889d9c1a9e..b5071941f4297e9641b44ac3b0ecc533797912df 100644 (file)
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.simantics.scenegraph.g2d.nodes;
 
+import java.awt.Graphics2D;
 import java.awt.geom.Rectangle2D;
 
 public class UnboundedNode extends SingleElementNode {
@@ -22,4 +23,12 @@ public class UnboundedNode extends SingleElementNode {
         return null;
     }
 
+    @Override
+    public void beforeRender(Graphics2D g) {
+    }
+
+    @Override
+    public void afterRender(Graphics2D g) {
+    }
+
 }
index 80b9a8a52c288207c5eb56f1c9ffc5989d0ddd5e..615899a59eef25676ff17b0cbdcb69ca0d62d1b8 100644 (file)
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Function;
 
 import org.simantics.scenegraph.IDynamicSelectionPainterNode;
 import org.simantics.scenegraph.ILookupService;
@@ -276,6 +277,7 @@ public final class NodeUtil {
         printSceneGraph(System.out, 0, node);
     }
 
+    @FunctionalInterface
     public static interface NodeProcedure<T> {
         T execute(INode node, String id);
     }
@@ -324,6 +326,47 @@ public final class NodeUtil {
         return result;
     }
 
+    /**
+     * Recursively iterates through all child nodes of the specified node and
+     * for those nodes that are of class <code>ofClass</code>, invokes
+     * <code>consumer</code>.
+     * 
+     * @param node
+     * @param ofClass
+     * @param consumer
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends INode> INode forChildrenDeep(INode node, Class<T> ofClass, Function<T, INode> func) {
+        return forChildrenDeep(node, n -> ofClass.isInstance(n) ? func.apply((T) n) : null);
+    }
+
+    public static <T extends INode> INode forChildrenDeep(INode node, Function<INode, INode> func) {
+        INode ret = func.apply(node);
+        if (ret != null)
+            return ret;
+
+        if (node instanceof ParentNode<?>) {
+            if (node instanceof G2DParentNode) {
+                G2DParentNode g2dpn = (G2DParentNode) node;
+                for (IG2DNode n : g2dpn.getSortedNodes()) {
+                    INode r = forChildrenDeep(n, func);
+                    if (r != null) {
+                        return r;
+                    }
+                }
+            } else {
+                for (INode n : ((ParentNode<?>) node).getNodes()) {
+                    INode r = forChildrenDeep(n, func);
+                    if (r != null) {
+                        return r;
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
     public static final int countTreeNodes(INode node) {
         int result = 1;
         if (node instanceof ParentNode<?>) {
@@ -336,11 +379,12 @@ public final class NodeUtil {
         return result;
     }
 
-    public static final void printTreeNodes(INode node, StringBuilder builder) {
+    public static final StringBuilder printTreeNodes(INode node, StringBuilder builder) {
         printTreeNodes(node, 0, builder);
+        return builder;
     }
 
-    public static final void printTreeNodes(INode node, int indent, StringBuilder builder) {
+    public static final StringBuilder printTreeNodes(INode node, int indent, StringBuilder builder) {
         for (int i = 0; i < indent; i++)
             builder.append(" ");
         builder.append(node.toString() + "\n");
@@ -351,6 +395,7 @@ public final class NodeUtil {
                 printTreeNodes(n, indent+2, builder);
             }
         }
+        return builder;
     }
 
     public static final <T extends INode> Set<T> collectNodes(INode node, Class<T> clazz) {
index 603cdaf4881c8a8eea8b1fca9f21d3908144eb28..10a24ddce9b324f127f628c017734b8079a6fd5e 100644 (file)
@@ -73,5 +73,6 @@ Export-Package: org.cojen.classfile,
  org.simantics.scl.compiler.types.kinds,
  org.simantics.scl.compiler.types.util
 Bundle-ClassPath: .
-Service-Component: OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml
+Service-Component: OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml,
+ OSGI-INF/org.simantics.scl.compiler.elaboration.java.LoggingModule.xml
 Import-Package: org.osgi.service.component.annotations
diff --git a/bundles/org.simantics.scl.compiler/OSGI-INF/org.simantics.scl.compiler.elaboration.java.LoggingModule.xml b/bundles/org.simantics.scl.compiler/OSGI-INF/org.simantics.scl.compiler.elaboration.java.LoggingModule.xml
new file mode 100644 (file)
index 0000000..bad60b1
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.simantics.scl.compiler.elaboration.java.LoggingModule">
+   <implementation class="org.simantics.scl.compiler.elaboration.java.LoggingModule"/>
+</scr:component>
\ No newline at end of file
index 77e91428448cd64cc4d5e3e880710d3498b286d8..55856a03e90fdc9712885feb95cf76bd983aa8a7 100644 (file)
@@ -2,4 +2,5 @@ source.. = src/
 output.. = bin/
 bin.includes = META-INF/,\
                .,\
-               OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml
+               OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml,\
+               OSGI-INF/org.simantics.scl.compiler.elaboration.java.LoggingModule.xml
index 7c6d53ac8f698171b3275f533925afb68bee1698..652adf93efc769cb30cce495d99a53ed665bd35b 100644 (file)
@@ -23,6 +23,7 @@ import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
@@ -38,6 +39,7 @@ import org.simantics.scl.compiler.module.ImportDeclaration;
 import gnu.trove.map.hash.THashMap;
 
 public class DeclarationClassification {
+    DModuleHeader moduleHeader;
     ArrayList<ImportDeclaration> importsAst = new ArrayList<ImportDeclaration>();
     ArrayList<DDataAst> dataTypesAst = new ArrayList<DDataAst>();
     ArrayList<DTypeAst> typeAliasesAst = new ArrayList<DTypeAst>();
@@ -106,6 +108,8 @@ public class DeclarationClassification {
             handle((DMappingRelationAst)declaration);
         else if(declaration instanceof DRelationAst)
             handle((DRelationAst)declaration);
+        else if(declaration instanceof DModuleHeader)
+            handle((DModuleHeader)declaration);
         else
             throw new InternalCompilerError("Unknown declaration " + declaration.getClass().getSimpleName());
     }
@@ -380,6 +384,10 @@ public class DeclarationClassification {
         mappingRelationsAst.add(declaration);
     }
     
+    public void handle(DModuleHeader declaration) {
+        moduleHeader = declaration;
+    }
+    
     public void addValueDocumentation(String valueName, DDocumentationAst documentation) {
         DDocumentationAst oldDoc = valueDocumentation.put(valueName, documentation);
         if(oldDoc != null) {
index 0971641e8b4470b2938f2cc8ac9660dc58a7d316..898f6c0a5680c88bad669e56c5395a5fe65d0164 100644 (file)
@@ -59,6 +59,7 @@ import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
 import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable;
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
@@ -68,6 +69,7 @@ import org.simantics.scl.compiler.internal.deriving.InstanceDeriver;
 import org.simantics.scl.compiler.internal.deriving.InstanceDerivers;
 import org.simantics.scl.compiler.internal.elaboration.profiling.BranchPointInjector;
 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
@@ -90,6 +92,8 @@ import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.module.ImportDeclaration;
+import org.simantics.scl.compiler.module.InvalidModulePathException;
+import org.simantics.scl.compiler.module.ModuleUtils;
 import org.simantics.scl.compiler.module.repository.ImportFailure;
 import org.simantics.scl.compiler.module.repository.ImportFailureException;
 import org.simantics.scl.compiler.types.TCon;
@@ -116,7 +120,9 @@ public class Elaboration {
     private final CompilationContext compilationContext;
     private final ErrorLog errorLog;
     private final String moduleName;
+    private final ModuleHeader moduleHeader;
     private final ArrayList<ImportDeclaration> importsAst;
+    private final JavaReferenceValidatorFactory jrvFactory;
     final JavaReferenceValidator<Object, Object, Object, Object> javaReferenceValidator;
     private final ValueRepository valueDefinitionsAst;
     private final RelationRepository relationDefinitionsAst;
@@ -131,18 +137,23 @@ public class Elaboration {
     THashMap<String, ClassRef> classRefs = new THashMap<String, ClassRef>();
     THashMap<String, BranchPoint[]> branchPoints; 
     
-    @SuppressWarnings("unchecked")
     public Elaboration(CompilationContext compilationContext, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory,
-            String moduleName, ArrayList<ImportDeclaration> importsAst,
-            JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator,
+            String moduleName, ModuleHeader moduleHeader, ArrayList<ImportDeclaration> importsAst,
+            JavaReferenceValidatorFactory jrvFactory,
             ValueRepository valueDefinitionsAst,
             RelationRepository relationDefinitionsAst) {
         this.compilationContext = compilationContext;
         this.errorLog = compilationContext.errorLog;
         this.moduleName = moduleName;
+        this.moduleHeader = moduleHeader;
         importsAst = processRelativeImports(importsAst);
         this.importsAst = importsAst;
-        this.javaReferenceValidator = (JavaReferenceValidator<Object, Object, Object, Object>)javaReferenceValidator;
+        this.jrvFactory = jrvFactory;
+        this.javaReferenceValidator = moduleHeader == null || moduleHeader.classLoader == null
+                ? jrvFactory.getDefaultJavaReferenceValidator()
+                : jrvFactory.getJavaReferenceValidator(moduleHeader.classLoader);
+        if(javaReferenceValidator == null)
+            errorLog.log(moduleHeader.classLoaderLocation, "Didn't find the specified class loader.");
         this.valueDefinitionsAst = valueDefinitionsAst;
         this.relationDefinitionsAst = relationDefinitionsAst;
 
@@ -175,14 +186,16 @@ public class Elaboration {
         ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
         for(ImportDeclaration relativeImport : relativeImports) {
             if(relativeImport.moduleName.startsWith(".")) {
-                String absoluteModuleName = convertRelativeModulePath(relativeImport.location, relativeImport.moduleName);
-                if(absoluteModuleName != null) {
+                               try {
+                                       String absoluteModuleName = ModuleUtils.resolveAbsolutePath(moduleName, relativeImport.moduleName);
                     ImportDeclaration absoluteImport = new ImportDeclaration(
                             absoluteModuleName, relativeImport.localName,
                             relativeImport.reexport, relativeImport.spec);
                     absoluteImport.location = relativeImport.location;
                     absoluteImports.add(absoluteImport);
-                }
+                               } catch (InvalidModulePathException e) {
+                                       errorLog.log(relativeImport.location, e.getMessage());
+                               }
             }
             else
                 absoluteImports.add(relativeImport);
@@ -190,31 +203,6 @@ public class Elaboration {
         return absoluteImports;
     }
 
-    private String convertRelativeModulePath(long location, String relativeModuleName) {
-        String originalRelativeModuleName = relativeModuleName;
-        int p = moduleName.lastIndexOf('/');
-        String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
-        while(relativeModuleName.startsWith(".")) {
-            if(relativeModuleName.startsWith("./")) {
-                relativeModuleName = relativeModuleName.substring(2);
-            }
-            else if(relativeModuleName.startsWith("../")) {
-                relativeModuleName = relativeModuleName.substring(3);
-                if(parentPackage.isEmpty()) {
-                    errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
-                    return null;
-                }
-                p = parentPackage.lastIndexOf('/');
-                parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
-            }
-            else {
-                errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
-                return null;
-            }
-        }
-        return parentPackage + "/" + relativeModuleName;
-    }
-
     public void addTypesToEnvironment(
             ArrayList<DDataAst> dataTypesAst,
             ArrayList<DTypeAst> typeAliasesAst,
@@ -653,15 +641,12 @@ public class Elaboration {
             if(annotations != null) {
                 for(DAnnotationAst annotation : annotations)
                     if(annotation.id.text.equals("@JavaName")) {
-                        Expression p0 = annotation.parameters[0];
-                        if(p0 instanceof EVar)
-                            javaName = ((EVar)p0).name;
-                        else if(p0 instanceof ELiteral) {
-                            ELiteral lit = (ELiteral)p0;
-                            javaName = ((StringConstant)lit.getValue()).getValue();
-                        }
+                        String temp = AnnotationUtils.processStringAnnotation(errorLog, annotation);
+                        if(temp != null)
+                            javaName = temp;
                     }
                     else if(annotation.id.text.equals("@private")) {
+                        AnnotationUtils.processTagAnnotation(errorLog, annotation);
                         isPrivate = true;
                     }
             }
index 29136b60935662d0e57bf91534959dfa4b9e7bf7..65e89edf1bc7c26fb4e8c1563083647b6d1cf231 100644 (file)
@@ -8,9 +8,12 @@ import java.util.Map;
 import org.simantics.scl.compiler.environment.EnvironmentFactory;
 import org.simantics.scl.compiler.errors.ErrorLog;
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLParserOptions;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
 import org.simantics.scl.compiler.top.ModuleInitializer;
@@ -29,8 +32,11 @@ public class SCLCompiler {
     private CompilationTimer timer;
     private ModuleCompilationOptions options;
     
-    public SCLCompiler(ModuleCompilationOptions options) {
+    JavaReferenceValidatorFactory jrvFactory;
+    
+    public SCLCompiler(ModuleCompilationOptions options, JavaReferenceValidatorFactory jrvFactory) {
         this.options = options == null ? ModuleCompilationOptions.STANDARD_OPTIONS : options;
+        this.jrvFactory = jrvFactory;
     }
 
     @SuppressWarnings("unchecked")
@@ -38,6 +44,7 @@ public class SCLCompiler {
         if(SCLCompilerConfiguration.ENABLE_TIMING) initializeTiming();
         try {
             SCLParserImpl parser = new SCLParserImpl(sourceReader);
+            parser.setParserOptions(SCLParserOptions.MODULE_DEFAULT);
             if(!parser.isEmpty())
             for(DeclarationAst declaration : (ArrayList<DeclarationAst>)parser.parseModule())
                 declarations.handle(declaration);
@@ -61,16 +68,16 @@ public class SCLCompiler {
     
     public void compile(
             EnvironmentFactory localEnvironmentFactory,
-            String moduleName,
-            JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator) {
+            String moduleName) {
         try {
             if(hasErrors()) return;
             Elaboration elaboration = new Elaboration(compilationContext,
                     timer,
                     localEnvironmentFactory,
                     moduleName,
+                    ModuleHeader.process(compilationContext.errorLog, declarations.moduleHeader),
                     declarations.importsAst,
-                    javaReferenceValidator,
+                    jrvFactory,
                     declarations.valueDefinitionsAst,
                     declarations.relationDefinitionsAst);
             if(options.computeCoverage)
@@ -159,6 +166,7 @@ public class SCLCompiler {
                     codeGeneration.externalConstants);
             
             module.setClasses(classes);
+            module.setParentClassLoader(elaboration.javaReferenceValidator.getClassLoader());
             module.setModuleInitializer(moduleInitializer);
             module.setBranchPoints(elaboration.branchPoints);
             if(compilationContext.errorLog.hasErrorsOrWarnings())
index fb7334cd2b2cf52cdbd1faf85dc266b762af9bc8..8cc088b955b8ded475ba86d150551f5a5f2ec44c 100644 (file)
@@ -5,8 +5,30 @@ import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
 import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral;
 import org.simantics.scl.compiler.elaboration.expressions.EVar;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
 
 public class AnnotationUtils {
+    /**
+     * Processes an annotation of form
+     * <pre>&#64;Annotation "text"</pre>
+     * or
+     * <pre>&#64;Annotation text</pre>
+     */
+    public static String processStringAnnotation(ErrorLog errorLog, DAnnotationAst annotation) {
+        if(annotation.parameters.length != 1)
+            errorLog.log(annotation.location, "Expected one string parameter for " + annotation.id.text);
+        String result = extractString(annotation.parameters[0]);
+        if(result == null)
+            errorLog.log(annotation.location, "Expected a string parameter for " + annotation.id.text);
+        return result;
+    }
+    
+    public static void processTagAnnotation(ErrorLog errorLog, DAnnotationAst annotation) {
+        if(annotation.parameters.length != 0)
+            errorLog.log(annotation.location, "Expected no parameters for " + annotation.id.text);
+    }
+    
     public static String extractString(Expression expression) {
         if(expression instanceof EVar)
             return ((EVar)expression).name;
index 7935257ace56ba7db959cb6b2d985225a42f74d8..14808c820f3b4c91f5ac305645ff9b9ffc1d3260 100644 (file)
@@ -348,6 +348,8 @@ public class Builtins extends ConcreteModule {
             
             addValue("visitBranchPoint", VisitBranchPoint.INSTANCE);
         }
+        
+        setParentClassLoader(getClass().getClassLoader());
     }
     
     @Override
index cb39346e4a730483b2948e304c803d4805b9af20..e412a11689f708e3dd27679a82d468173743a9d8 100644 (file)
@@ -137,6 +137,8 @@ public class JavaModule extends ConcreteModule {
                 "java/lang/Object", "hashCode", Types.NO_EFFECTS, Types.INTEGER, A));
         addValue("toString", new JavaMethod(true, 
                 "java/lang/Object", "toString", Types.NO_EFFECTS, Types.STRING, A));
+        
+        setParentClassLoader(getClass().getClassLoader());
     }
     
     static Expression createLiteral(FunctionValue value) {
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/LoggingModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/LoggingModule.java
new file mode 100644 (file)
index 0000000..fa50596
--- /dev/null
@@ -0,0 +1,64 @@
+package org.simantics.scl.compiler.elaboration.java;
+
+import org.cojen.classfile.TypeDesc;
+import org.osgi.service.component.annotations.Component;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.JavaMethod;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.macros.MacroRule;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
+import org.simantics.scl.compiler.module.ConcreteModule;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component
+public class LoggingModule extends ConcreteModule {
+
+    private static String[] LOGGING_METHODS = new String[] {
+            "trace", "debug", "info", "warn", "error" 
+    };
+
+    public LoggingModule() {
+        super("Logging");
+
+        // Logger
+        TCon Logger = Types.con(getName(), "Logger");
+        StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
+        loggerConstructor.external = true;
+        addTypeDescriptor("Logger", loggerConstructor);
+
+        // Common types
+        Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
+
+        // Add logging methods
+        for(String methodName : LOGGING_METHODS) {
+            JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
+            SCLValue value = new SCLValue(Name.create(getName(), methodName));
+            value.setType(loggingType);
+            value.setMacroRule(new MacroRule() {
+                @Override
+                public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
+                    ConcreteModule module = context.getCompilationContext().module;
+                    apply.set(new ELiteral(javaMethod), new Expression[] {
+                            new EExternalConstant(LoggerFactory.getLogger(module.getName().replaceAll("/", ".")), Logger),
+                            apply.parameters[0]
+                    });
+                    return apply;
+                }
+            });
+            addValue(value);
+        }
+        
+        setParentClassLoader(LoggerFactory.class.getClassLoader());
+    }
+
+}
index 6bdaaea7bfda2b0d26a89944b09e6f6be0a1d289..434f2da6e13ff7b8249d6373aa7595c87eb7aca6 100644 (file)
@@ -282,6 +282,7 @@ public class MinigraphModule extends ConcreteModule {
                 return new ResourceAttribute(name);
             }
         });
+        setParentClassLoader(getClass().getClassLoader());
     }
     
     private static class ResourceAttribute implements SCLEntityType.Attribute {
index c9f33ec50c7727e8a9c789858de926bfce31a282..aaab03e1aae8c3e49686ec7d1960c4dc9dbf1b44 100644 (file)
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 import org.simantics.scl.compiler.constants.SCLConstant;
 import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
@@ -21,6 +22,7 @@ import org.simantics.scl.compiler.internal.codegen.utils.Printable;
 import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
 import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;
 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.SSAUtils;
 import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
 import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
@@ -281,27 +283,42 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
             context.markModified("improve-parameters");
     }
 
+    private static Constant getOnlyPossibleValue(Type type) {
+        type = Types.canonical(type);
+        if(type == Types.UNIT)
+            return NoRepConstant.UNIT;
+        else if(type == Types.PUNIT)
+            return NoRepConstant.PUNIT;
+        return null; 
+    }
+    
     private boolean tryToImproveParameter(int position) {
         BoundVar parameter = parameters[position];
-        Val constant = null;
-        ValRef constantRef = null;
-        for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
-            Jump jump = (Jump)ref.getParent();
-            ValRef valRef = jump.getParameters()[position];
-            Val val = valRef.getBinding();
-            if(val == parameter)
-                continue;
-            if(constant == null) {
-                constant = val;
-                constantRef = valRef;
-                continue;
+        Constant onlyPossibleValue = getOnlyPossibleValue(parameter.getType());
+        if(onlyPossibleValue == null) {
+            Val constant = null;
+            ValRef constantRef = null;
+            for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
+                Jump jump = (Jump)ref.getParent();
+                ValRef valRef = jump.getParameters()[position];
+                Val val = valRef.getBinding();
+                if(val == parameter)
+                    continue;
+                if(constant == null) {
+                    constant = val;
+                    constantRef = valRef;
+                    continue;
+                }
+                if(val != constant)
+                    return false;
             }
-            if(val != constant)
-                return false;
+            if(constant == null)
+                return false; // This is a strange case, because we cannot get the parameter anywhere
+            parameter.replaceBy(constantRef);
+        }
+        else {
+            parameter.replaceBy(onlyPossibleValue);
         }
-        if(constant == null)
-            return false; // This is a strange case, because we cannot get the parameter anywhere
-        parameter.replaceBy(constantRef);
         
         for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
             Jump jump = (Jump)ref.getParent();
@@ -331,32 +348,72 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
         return result;
     }
     
+    /*
+     * This method assumes that the exit of the block is Jump.
+     */
     private boolean optimizeTailSelfCall() {
-        Jump jump = (Jump)exit;
-        if(jump.getTarget().getBinding() != parent.returnCont)
-            return false;
-        if(jump.getParameters().length != 1)
-            return false;
+        // The last statement of the block is LetApply that calls the parent function with right number of parameters 
         if(lastStatement == null || !(lastStatement instanceof LetApply))
             return false;
         LetApply apply = (LetApply)lastStatement;
-        SSABlock initialBlock = parent.firstBlock;
-        if(initialBlock.parameters.length != apply.getParameters().length)
-            return false;
         Val function = apply.getFunction().getBinding();
         if(function != parent.target)
             return false;
+        SSABlock initialBlock = parent.firstBlock;
+        if(initialBlock.parameters.length != apply.getParameters().length)
+            return false;
+
+        // The jump is a return (with one parameter)
+        // The parameter of the jump is the target of LetApply
+        Jump jump = (Jump)exit;
+        Cont targetCont = jump.getTarget().getBinding();
+        if(targetCont != parent.returnCont) {
+            SSABlock targetBlock = (SSABlock)targetCont;
+            if(targetBlock.firstStatement != null)
+                return false;
+            if(!(targetBlock.exit instanceof Jump))
+                return false;
+            Jump targetJump = (Jump)targetBlock.exit;
+            if(targetJump.getTarget().getBinding() != parent.returnCont)
+                return false;
+            if(targetJump.getParameters().length != 1)
+                return false;
+            
+            BoundVar applyTarget = apply.getTarget();
+            ValRef targetJumpParameter = targetJump.getParameter(0);
+            isSameParam: if(!SSAUtils.representSameValue(applyTarget, targetJumpParameter)) {
+                BoundVar[] targetBlockParameters = targetBlock.getParameters();
+                for(int i=0;i<targetBlockParameters.length;++i) {
+                    if(targetJumpParameter.getBinding() == targetBlockParameters[i]
+                            && jump.getParameter(i).getBinding() == applyTarget)
+                        break isSameParam;
+                }
+                return false;
+            }
+        }
+        else {
+            if(jump.getParameters().length != 1)
+                return false;
+            if(!SSAUtils.representSameValue(apply.getTarget(), jump.getParameter(0)))
+                return false;
+        }
         
         // Do modifications
         apply.detach();
         apply.getFunction().remove();
         jump.getTarget().remove();
         jump.setTarget(initialBlock.createOccurrence());
+        for(ValRef parameter : jump.getParameters())
+            parameter.remove();
         jump.setParameters(apply.getParameters());
         
         return true;
     }
 
+    /**
+     * Assumes that this block has no statements, the block is not the first block
+     * and the exit of the block is Jump.
+     */
     private boolean etaBlock(SSASimplificationContext context) {
         Jump jump = (Jump)exit;
         if(parameters.length != jump.getParameters().length)
@@ -436,7 +493,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
         block.detach();
         
         jump.destroy();
-        setExit(block.exit);       
+        setExit(block.exit);
         
         /*System.out.println(">> AFTER INLINE >>");
         System.out.println(getParent());
index 68dd82f15f4bb1c76d5b68c07f58cfc501e3f66c..ab643f9a15b1669be060ae165c07a403cb3888c3 100644 (file)
@@ -5,6 +5,7 @@ import java.util.Arrays;
 
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
 import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
 import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
@@ -173,12 +174,88 @@ public final class SSAFunction extends SSAClosure {
     public void simplify(SSASimplificationContext context) {
         for(SSABlock block = firstBlock; block != null; block = block.next)
             block.simplify(context);
-        if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement &&
-                firstBlock.firstStatement instanceof LetFunctions) {
-            simplifySingleLambda(context);            
+        if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement) {
+            if(firstBlock.firstStatement instanceof LetApply)
+                simplifySingleApply(context);
+            else if(firstBlock.firstStatement instanceof LetFunctions)
+                simplifySingleLambda(context);
         }
     }
     
+    
+    /**
+     * Simplifies the following kind of function definition
+     *     \x -> f x
+     * to
+     *     f
+     */
+    private void simplifySingleApply(SSASimplificationContext context) {
+        if(!(parent instanceof LetFunctions) || parent.getFirstClosure().next != null)
+            return;
+        LetApply apply = (LetApply)firstBlock.firstStatement;
+        if(!(firstBlock.exit instanceof Jump))
+            return;
+        Jump exit = (Jump)firstBlock.exit;
+        if(exit.getTarget().getBinding() != returnCont)
+            return;
+        if(exit.getParameter(0).getBinding() != apply.getTarget())
+            return;
+        BoundVar[] functionParameters = getParameters();
+        ValRef[] applyParameters = apply.getParameters();
+        if(functionParameters.length > applyParameters.length)
+            return;
+        int extraApplyParameters = applyParameters.length - functionParameters.length;
+        for(int i=0;i<functionParameters.length;++i)
+            if(!representSameValues(functionParameters[i], applyParameters[extraApplyParameters+i]))
+                return;
+        for(int i=0;i<extraApplyParameters;++i) {
+            Val b = applyParameters[i].getBinding();
+            if(b instanceof BoundVar) {
+                BoundVar bv = (BoundVar)b;
+                if(bv == target || bv.getParent() == firstBlock)
+                    return;
+            }
+        }
+        if(!(target instanceof BoundVar))
+            return;
+        
+        // Transform
+        
+        LetFunctions binder = (LetFunctions)parent;
+        SSAFunction parentFunction = binder.getParentFunction();
+        if(extraApplyParameters > 0) {
+            //System.out.println("-------------------------------------------------------------");
+            //System.out.println(parentFunction);
+            //System.out.println("-------------------------------------------------------------");
+            apply.setTarget((BoundVar)target);
+            apply.setParameters(Arrays.copyOf(applyParameters, extraApplyParameters));
+            apply.insertBefore(binder);
+            binder.detach();
+            //System.out.println(parentFunction);
+            //System.out.println("-------------------------------------------------------------");
+        }
+        else {
+            binder.detach();
+            ((BoundVar)target).replaceBy(apply.getFunction());
+        }
+        context.markModified("SSAFunction.eta-reduce");
+    }
+    
+    private boolean representSameValues(BoundVar boundVar, ValRef valRef) {
+        Val val = valRef.getBinding(); 
+        if(val == boundVar && valRef.getTypeParameters().length == 0)
+            return true;
+        if(val instanceof NoRepConstant && Types.equals(valRef.getType(), boundVar.getType()))
+            return true;
+        return false;
+    }
+
+    /**
+     * Simplifies the following kind of function definition
+     *     \x -> \y -> e
+     * to
+     *     \x y -> e
+     */
     private void simplifySingleLambda(SSASimplificationContext context) {
         LetFunctions letF = (LetFunctions)firstBlock.firstStatement;
         if(!(letF.getFirstClosure() instanceof SSAFunction))
@@ -202,7 +279,7 @@ public final class SSAFunction extends SSAClosure {
         lastBlock = f.lastBlock;
         
         firstBlock.firstStatement = firstBlock.lastStatement = null;
-        setReturnCont(f.getReturnCont());        
+        setReturnCont(f.getReturnCont());
         effect = f.effect;
         BoundVar[] newParameters = BoundVar.copy(f.firstBlock.parameters);
         firstBlock.setParameters(BoundVar.concat(getParameters(), newParameters));
index 0bcb3dd596e3bc03cbc91779d40232ce3d787c02..27f853e0283b3d714757f4d3369cab4379cf470d 100644 (file)
@@ -6,6 +6,7 @@ import org.objectweb.asm.Label;
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.constants.BooleanConstant;
 import org.simantics.scl.compiler.constants.IntegerConstant;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
 import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
@@ -223,11 +224,15 @@ public class Switch extends SSAExit implements ValRefBinder {
             context.markModified("switch-to-if");
             newExit.simplify(context);
         }
-        else if(branches.length == 1 && branches[0].constructor == null) {
+        else if(branches.length == 1 && isConstructorParameterless(branches[0])) {
             scrutinee.remove();
             getParent().setExit(new Jump(branches[0].cont));
         }
     }
+    
+    private static boolean isConstructorParameterless(BranchRef branch) {
+        return branch.constructor == null || branch.constructor instanceof NoRepConstant;
+    }
 
     @Override
     public void collectFreeVariables(SSAFunction function,
index 84289af0d2f2672ed40669bfc83c5b98a7f7a968..994e2d63f75cc1c8d26804e672fd15cdf6b8c9a1 100644 (file)
@@ -76,5 +76,10 @@ public enum DummyJavaReferenceValidator implements JavaReferenceValidator<Object
     public boolean isPublic(Object clazz) {
         return false;
     }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        throw new UnsupportedOperationException();
+    }
     
 }
index d4fb5769b86c526a76e83f16a5a418f762ce6638..189dcb2eb385a9d88029a9b9dddaad916d055b0f 100644 (file)
@@ -40,4 +40,6 @@ public interface JavaReferenceValidator<Class,Method,Field,Constructor> {
      * class is not found.
      */
     ClassRef getClassRef(String className);
+
+    ClassLoader getClassLoader();
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/JavaReferenceValidatorFactory.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/JavaReferenceValidatorFactory.java
new file mode 100644 (file)
index 0000000..55d42c2
--- /dev/null
@@ -0,0 +1,6 @@
+package org.simantics.scl.compiler.internal.codegen.types;
+
+public interface JavaReferenceValidatorFactory {
+    JavaReferenceValidator<Object, Object, Object, Object> getJavaReferenceValidator(String context);
+    JavaReferenceValidator<Object, Object, Object, Object> getDefaultJavaReferenceValidator();
+}
index 8b36a8148f794f31164c3422cf56b65e955a8cb3..4ee0ab4f870653b310609836597a42d0541dcd02 100644 (file)
@@ -14,5 +14,10 @@ public class RuntimeJavaReferenceValidator extends AbstractRuntimeJavaReferenceV
     public Class<?> findClass(TypeDesc name) {
         return name.toClass(classLoader);
     }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return classLoader;
+    }
     
 }
index cc8f3e0c5ab5a7f5dfefb8cf43b77b28b76c756e..81f7b117a82f61f7ade860cd1362d5b4a85559e3 100644 (file)
@@ -93,72 +93,75 @@ public class CodeBuilderUtils {
             tsmb.finish();
         }
         
-        if(generateEqualsAndHashCode) {
-            // Create equals
-            {
-                TypeDesc CLASS = TypeDesc.forClass(Class.class);
+        if(generateEqualsAndHashCode)
+            implementHashCodeAndEquals(classBuilder, recordName, fieldNamePrefix, types);
+    }
 
-                MethodBuilderBase tsmb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[1]);
-                LocalVariable parameter = tsmb.getParameter(0);
-                Label success = tsmb.createLabel();
-                Label failure = tsmb.createLabel();
+    public static void implementHashCodeAndEquals(ClassBuilder classBuilder, String recordName, String fieldNamePrefix, TypeDesc[] types) {
+        // Create equals
+        {
+            TypeDesc CLASS = TypeDesc.forClass(Class.class);
 
-                // Check type
-                tsmb.loadThis();
-                tsmb.loadLocal(parameter);
-                tsmb.ifComparisonBranch(success, "==", TypeDesc.OBJECT);
-                tsmb.loadLocal(parameter);
-                tsmb.ifNullBranch(failure, true);
-                tsmb.loadLocal(parameter);
-                tsmb.invokeVirtual("java/lang/Object", "getClass", CLASS, Constants.EMPTY_TYPEDESC_ARRAY);
-                tsmb.loadThis();
-                tsmb.invokeVirtual("java/lang/Object", "getClass", CLASS, Constants.EMPTY_TYPEDESC_ARRAY);
-                tsmb.ifComparisonBranch(failure, "!=", CLASS);
-                tsmb.loadLocal(parameter);
-                tsmb.checkCast(classBuilder.getType());
-                LocalVariable other = tsmb.createLocalVariable("other", classBuilder.getType());
-                tsmb.storeLocal(other);
+            MethodBuilderBase tsmb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[1]);
+            LocalVariable parameter = tsmb.getParameter(0);
+            Label success = tsmb.createLabel();
+            Label failure = tsmb.createLabel();
 
-                // Compare fields
-                for(int i=0;i<types.length;++i) {
-                    TypeDesc type = types[i];
-                    if(type.equals(TypeDesc.VOID))
-                        continue;
-                    tsmb.loadThis();
-                    tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
-                    tsmb.loadLocal(other);
-                    tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
-                    equals(tsmb, type, failure);
-                }
+            // Check type
+            tsmb.loadThis();
+            tsmb.loadLocal(parameter);
+            tsmb.ifComparisonBranch(success, "==", TypeDesc.OBJECT);
+            tsmb.loadLocal(parameter);
+            tsmb.ifNullBranch(failure, true);
+            tsmb.loadLocal(parameter);
+            tsmb.invokeVirtual("java/lang/Object", "getClass", CLASS, Constants.EMPTY_TYPEDESC_ARRAY);
+            tsmb.loadThis();
+            tsmb.invokeVirtual("java/lang/Object", "getClass", CLASS, Constants.EMPTY_TYPEDESC_ARRAY);
+            tsmb.ifComparisonBranch(failure, "!=", CLASS);
+            tsmb.loadLocal(parameter);
+            tsmb.checkCast(classBuilder.getType());
+            LocalVariable other = tsmb.createLocalVariable("other", classBuilder.getType());
+            tsmb.storeLocal(other);
 
-                // Return
-                tsmb.setLocation(success);
-                tsmb.loadConstant(true);
-                tsmb.returnValue(TypeDesc.BOOLEAN);
-                tsmb.setLocation(failure);
-                tsmb.loadConstant(false);
-                tsmb.returnValue(TypeDesc.BOOLEAN);
-                tsmb.finish();
+            // Compare fields
+            for(int i=0;i<types.length;++i) {
+                TypeDesc type = types[i];
+                if(type.equals(TypeDesc.VOID))
+                    continue;
+                tsmb.loadThis();
+                tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
+                tsmb.loadLocal(other);
+                tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
+                equals(tsmb, type, failure);
             }
 
-            // Create hashCode
-            {
-                MethodBuilderBase tsmb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "hashCode", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);
-                tsmb.loadConstant(recordName.hashCode());
-                for(int i=0;i<types.length;++i) {
-                    TypeDesc type = types[i];
-                    if(type.equals(TypeDesc.VOID))
-                        continue;
-                    tsmb.loadConstant(31);
-                    tsmb.math(Opcodes.IMUL);
-                    tsmb.loadThis();
-                    tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
-                    hashCode(tsmb, type);
-                    tsmb.math(Opcodes.IADD);
-                }
-                tsmb.returnValue(TypeDesc.INT);
-                tsmb.finish();
+            // Return
+            tsmb.setLocation(success);
+            tsmb.loadConstant(true);
+            tsmb.returnValue(TypeDesc.BOOLEAN);
+            tsmb.setLocation(failure);
+            tsmb.loadConstant(false);
+            tsmb.returnValue(TypeDesc.BOOLEAN);
+            tsmb.finish();
+        }
+
+        // Create hashCode
+        {
+            MethodBuilderBase tsmb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "hashCode", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);
+            tsmb.loadConstant(recordName.hashCode());
+            for(int i=0;i<types.length;++i) {
+                TypeDesc type = types[i];
+                if(type.equals(TypeDesc.VOID))
+                    continue;
+                tsmb.loadConstant(31);
+                tsmb.math(Opcodes.IMUL);
+                tsmb.loadThis();
+                tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
+                hashCode(tsmb, type);
+                tsmb.math(Opcodes.IADD);
             }
+            tsmb.returnValue(TypeDesc.INT);
+            tsmb.finish();
         }
     }
     
index e9d808c8c5eda034a40548e65aa7536e5ce96569..8db288a8976196486ec14ee0601ddbf4a14575b8 100644 (file)
@@ -93,7 +93,7 @@ public class ModuleBuilder {
             // Create fields
             CodeBuilderUtils.makeRecord(classBuilder, functionValue.toString(), Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "p",
                     Arrays.copyOf(parameterTypes, knownParametersCount),
-                    false);
+                    true);
             
             // Create apply
             {
@@ -131,7 +131,7 @@ public class ModuleBuilder {
                 for(int i=0;i<knownParametersCount;++i) {
                     mb.loadThis();
                     mb.loadLocal(mb.getParameter(i));
-                    mb.storeField(className, "p"+i, parameterTypes[i]);            
+                    mb.storeField(className, "p"+i, parameterTypes[i]);
                 }
                 mb.returnVoid();
                 mb.finish();
@@ -160,7 +160,9 @@ public class ModuleBuilder {
                 functionValue.applyExact(mb, parameters);
                 mb.box(functionValue.getReturnType());
                 mb.returnValue(TypeDesc.OBJECT);
-            }      
+            }
+            
+            CodeBuilderUtils.implementHashCodeAndEquals(classBuilder, functionValue.toString(), "p", parameterTypes);
         }
             
         // Finish
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/SSAUtils.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/SSAUtils.java
new file mode 100644 (file)
index 0000000..7de1ab4
--- /dev/null
@@ -0,0 +1,31 @@
+package org.simantics.scl.compiler.internal.codegen.utils;
+
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class SSAUtils {
+
+    public static boolean representSameValue(Val a, ValRef b) {
+        if(b.getTypeParameters().length > 0)
+            return false;
+        return representSameValue(a, b.getBinding());
+    }
+    
+    public static boolean representSameValue(Val a, Val b) {
+        if(a == b)
+            return true;
+        Type aT = a.getType();
+        Type bT = b.getType();
+        if(!Types.equals(aT, bT))
+            return false;
+        return isSingletonType(aT);
+    }
+
+    public static boolean isSingletonType(Type type) {
+        type = Types.canonical(type);
+        return type == Types.UNIT || type == Types.PUNIT;
+    }
+    
+}
index bccfa892832a05c2a024f5a7b0f3258c3e35c6c3..4efd2a8d404e7037925fd7d005d782e1fa5c8d3f 100644 (file)
@@ -11,6 +11,192 @@ import org.simantics.scl.runtime.tuple.Tuple0;
 
 public class ValueFromMethod {
 
+    private static final class Arity1Func extends FunctionImpl1<Object, Object> {
+        private final Method method;
+        private final boolean returnsVoid;
+
+        private Arity1Func(Method method, boolean returnsVoid) {
+            this.method = method;
+            this.returnsVoid = returnsVoid;
+        }
+
+        @Override
+        public Object apply(Object p0) {
+            try {
+                Object ret = method.invoke(null, p0);
+                return returnsVoid ? Tuple0.INSTANCE : ret;
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return method == null ? 0 : method.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Arity1Func other = (Arity1Func) obj;
+            return method.equals(other.method);
+        }
+    }
+
+    private static final class Arity2Func extends FunctionImpl2<Object, Object, Object> {
+        private final Method method;
+        private final boolean returnsVoid;
+
+        private Arity2Func(Method method, boolean returnsVoid) {
+            this.method = method;
+            this.returnsVoid = returnsVoid;
+        }
+
+        @Override
+        public Object apply(Object p0, Object p1) {
+            try {
+                Object ret = method.invoke(null, p0, p1);
+                return returnsVoid ? Tuple0.INSTANCE : ret;
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        @Override
+        public int hashCode() {
+            return method == null ? 0 : method.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Arity2Func other = (Arity2Func) obj;
+            return method.equals(other.method);
+        }
+    }
+
+    private static final class Arity3Func extends FunctionImpl3<Object, Object, Object, Object> {
+        private final Method method;
+        private final boolean returnsVoid;
+
+        private Arity3Func(Method method, boolean returnsVoid) {
+            this.method = method;
+            this.returnsVoid = returnsVoid;
+        }
+
+        @Override
+        public Object apply(Object p0, Object p1, Object p2) {
+            try {
+                Object ret = method.invoke(null, p0, p1, p2);
+                return returnsVoid ? Tuple0.INSTANCE : ret;
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        @Override
+        public int hashCode() {
+            return method == null ? 0 : method.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Arity3Func other = (Arity3Func) obj;
+            return method.equals(other.method);
+        }
+    }
+
+    private static final class Arity4Func extends FunctionImpl4<Object, Object, Object, Object, Object> {
+        private final Method method;
+        private final boolean returnsVoid;
+
+        private Arity4Func(Method method, boolean returnsVoid) {
+            this.method = method;
+            this.returnsVoid = returnsVoid;
+        }
+
+        @Override
+        public Object apply(Object p0, Object p1, Object p2, Object p3) {
+            try {
+                Object ret = method.invoke(null, p0, p1, p2, p3);
+                return returnsVoid ? Tuple0.INSTANCE : ret;
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        @Override
+        public int hashCode() {
+            return method == null ? 0 : method.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Arity4Func other = (Arity4Func) obj;
+            return method.equals(other.method);
+        }
+    }
+
+    private static final class ArityNFunc extends FunctionImplN {
+        private final Method method;
+        private final boolean returnsVoid;
+
+        private ArityNFunc(int arity, Method method, boolean returnsVoid) {
+            super(arity);
+            this.method = method;
+            this.returnsVoid = returnsVoid;
+        }
+
+        @Override
+        public Object doApply(Object... ps) {
+            try {
+                Object ret =  method.invoke(null, ps);
+                return returnsVoid ? Tuple0.INSTANCE : ret;
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        @Override
+        public int hashCode() {
+            return method == null ? 0 : method.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            ArityNFunc other = (ArityNFunc) obj;
+            return method.equals(other.method);
+        }
+    }
+
     public static Object getValueFromStaticMethod(final Method method) throws ReflectiveOperationException {
         int arity = method.getParameterTypes().length;
         final boolean returnsVoid = method.getReturnType().equals(void.class);
@@ -20,65 +206,15 @@ public class ValueFromMethod {
             return returnsVoid ? Tuple0.INSTANCE : ret;
         }
         case 1:
-            return new FunctionImpl1<Object,Object>() {
-                @Override
-                public Object apply(Object p0) {
-                    try {
-                        Object ret = method.invoke(null, p0);
-                        return returnsVoid ? Tuple0.INSTANCE : ret;
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            };
+            return new Arity1Func(method, returnsVoid);
         case 2:
-            return new FunctionImpl2<Object,Object,Object>() {
-                @Override
-                public Object apply(Object p0, Object p1) {
-                    try {
-                        Object ret = method.invoke(null, p0, p1);
-                        return returnsVoid ? Tuple0.INSTANCE : ret;
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            };
+            return new Arity2Func(method, returnsVoid);
         case 3:
-            return new FunctionImpl3<Object,Object,Object,Object>() {
-                @Override
-                public Object apply(Object p0, Object p1, Object p2) {
-                    try {
-                        Object ret = method.invoke(null, p0, p1, p2);
-                        return returnsVoid ? Tuple0.INSTANCE : ret;
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            };
+            return new Arity3Func(method, returnsVoid);
         case 4:
-            return new FunctionImpl4<Object,Object,Object,Object,Object>() {
-                @Override
-                public Object apply(Object p0, Object p1, Object p2, Object p3) {
-                    try {
-                        Object ret = method.invoke(null, p0, p1, p2, p3);
-                        return returnsVoid ? Tuple0.INSTANCE : ret;
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            };
+            return new Arity4Func(method, returnsVoid);
         default:
-            return new FunctionImplN(arity) {
-                @Override
-                public Object doApply(Object... ps) {
-                    try {
-                        Object ret =  method.invoke(null, ps);
-                        return returnsVoid ? Tuple0.INSTANCE : ret;
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            };
+            return new ArityNFunc(arity, method, returnsVoid);
         }
     }
     
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java
new file mode 100644 (file)
index 0000000..9ca5887
--- /dev/null
@@ -0,0 +1,38 @@
+package org.simantics.scl.compiler.internal.header;
+
+import org.simantics.scl.compiler.elaboration.expressions.annotations.AnnotationUtils;
+import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
+
+public class ModuleHeader {
+    public String classLoader;
+    public long classLoaderLocation;
+    
+    private void read(ErrorLog errorLog, DModuleHeader header) {
+        for(FieldAssignment assignment : header.fields)
+            switch(assignment.name) {
+            case "bundle":
+                if(assignment.value == null)
+                    errorLog.log(assignment.location, "Property classLoader needs to be given a string value.");
+                else {
+                    classLoader = AnnotationUtils.extractString(assignment.value);
+                    if(classLoader == null)
+                        errorLog.log(assignment.value.location, "Expected bundle name here.");
+                    else 
+                        classLoaderLocation = assignment.location;
+                }
+                break;
+            default:
+                errorLog.logWarning(assignment.location, "Unknown module header field was skipped.");
+            }
+    }
+    
+    public static ModuleHeader process(ErrorLog errorLog, DModuleHeader header) {
+        if(header == null)
+            return null;
+        ModuleHeader result = new ModuleHeader();
+        result.read(errorLog, header);
+        return result;
+    }
+}
index aac13af73abe661ddcc275f0e3f83908b6937e4f..0695ebb4da8396bf3be8f680568419aadadd8b36 100644 (file)
@@ -1,5 +1,7 @@
 package org.simantics.scl.compiler.internal.interpreted;
 
+import java.util.Arrays;
+
 import org.simantics.scl.runtime.function.FunctionImpl1;
 import org.simantics.scl.runtime.function.FunctionImpl2;
 import org.simantics.scl.runtime.function.FunctionImpl3;
@@ -7,11 +9,229 @@ import org.simantics.scl.runtime.function.FunctionImpl4;
 import org.simantics.scl.runtime.function.FunctionImplN;
 
 public class ILambda implements IExpression {
+    private final class Arity1Func extends FunctionImpl1 {
+        private final Object[] inheritedVariableBindings;
+
+        private Arity1Func(Object[] inheritedVariableBindings) {
+            this.inheritedVariableBindings = inheritedVariableBindings;
+        }
+
+        @Override
+        public Object apply(Object param0) {
+            Object[] newVariableBindings = new Object[variableBindingsLength];
+            int i = 0;;
+            for(;i < inheritedVariableBindings.length;++i)
+                newVariableBindings[i] = inheritedVariableBindings[i];
+            newVariableBindings[i] = param0;
+            return body.execute(newVariableBindings);
+        }
+
+        @Override
+        public String toString() {
+            return ILambda.this.toString(inheritedVariableBindings);
+        }
+
+        @Override
+        public int hashCode() {
+            return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
+        }
+
+        private ILambda getParent() {
+            return ILambda.this;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(obj == this)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            Arity1Func other = (Arity1Func)obj;
+            return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
+        }
+    }
+
+    private final class Arity2Func extends FunctionImpl2 {
+        private final Object[] inheritedVariableBindings;
+
+        private Arity2Func(Object[] inheritedVariableBindings) {
+            this.inheritedVariableBindings = inheritedVariableBindings;
+        }
+
+        @Override
+        public Object apply(Object param0, Object param1) {
+            Object[] newVariableBindings = new Object[variableBindingsLength];
+            int i = 0;;
+            for(;i < inheritedVariableBindings.length;++i)
+                newVariableBindings[i] = inheritedVariableBindings[i];
+            newVariableBindings[i++] = param0;
+            newVariableBindings[i] = param1;
+            return body.execute(newVariableBindings);
+        }
+
+        @Override
+        public String toString() {
+            return ILambda.this.toString(inheritedVariableBindings);
+        }
+        
+        @Override
+        public int hashCode() {
+            return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
+        }
+
+        private ILambda getParent() {
+            return ILambda.this;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(obj == this)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            Arity2Func other = (Arity2Func)obj;
+            return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
+        }
+    }
+
+    private final class Arity3Func extends FunctionImpl3 {
+        private final Object[] inheritedVariableBindings;
+
+        private Arity3Func(Object[] inheritedVariableBindings) {
+            this.inheritedVariableBindings = inheritedVariableBindings;
+        }
+
+        @Override
+        public Object apply(Object param0, Object param1, Object param2) {
+            Object[] newVariableBindings = new Object[variableBindingsLength];
+            int i = 0;;
+            for(;i < inheritedVariableBindings.length;++i)
+                newVariableBindings[i] = inheritedVariableBindings[i];
+            newVariableBindings[i++] = param0;
+            newVariableBindings[i++] = param1;
+            newVariableBindings[i] = param2;
+            return body.execute(newVariableBindings);
+        }
+
+        @Override
+        public String toString() {
+            return ILambda.this.toString(inheritedVariableBindings);
+        }
+        
+        @Override
+        public int hashCode() {
+            return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
+        }
+
+        private ILambda getParent() {
+            return ILambda.this;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(obj == this)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            Arity3Func other = (Arity3Func)obj;
+            return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
+        }
+    }
+
+    private final class Arity4Func extends FunctionImpl4 {
+        private final Object[] inheritedVariableBindings;
+
+        private Arity4Func(Object[] inheritedVariableBindings) {
+            this.inheritedVariableBindings = inheritedVariableBindings;
+        }
+
+        @Override
+        public Object apply(Object param0, Object param1, Object param2, Object param3) {
+            Object[] newVariableBindings = new Object[variableBindingsLength];
+            int i = 0;;
+            for(;i < inheritedVariableBindings.length;++i)
+                newVariableBindings[i] = inheritedVariableBindings[i];
+            newVariableBindings[i++] = param0;
+            newVariableBindings[i++] = param1;
+            newVariableBindings[i++] = param2;
+            newVariableBindings[i] = param3;
+            return body.execute(newVariableBindings);
+        }
+
+        @Override
+        public String toString() {
+            return ILambda.this.toString(inheritedVariableBindings);
+        }
+
+        @Override
+        public int hashCode() {
+            return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
+        }
+
+        private ILambda getParent() {
+            return ILambda.this;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(obj == this)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            Arity4Func other = (Arity4Func)obj;
+            return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
+        }
+    }
+
+    private final class ArityNFunc extends FunctionImplN {
+        private final Object[] inheritedVariableBindings;
+
+        private ArityNFunc(Object[] inheritedVariableBindings) {
+            super(arity);
+            this.inheritedVariableBindings = inheritedVariableBindings;
+        }
+
+        @Override
+        public Object doApply(Object... ps) {
+            Object[] newVariableBindings = new Object[variableBindingsLength];
+            int i = 0;;
+            for(;i < inheritedVariableBindings.length;++i)
+                newVariableBindings[i] = inheritedVariableBindings[i];
+            for(Object p : ps)
+                newVariableBindings[i++] = p;
+            return body.execute(newVariableBindings);
+        }
+
+        @Override
+        public String toString() {
+            return ILambda.this.toString(inheritedVariableBindings);
+        }
+
+        @Override
+        public int hashCode() {
+            return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
+        }
+
+        private ILambda getParent() {
+            return ILambda.this;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(obj == this)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            ArityNFunc other = (ArityNFunc)obj;
+            return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
+        }
+    }
+
     private final int[] inheritedVariableIds;
     private final int arity;
     private final int variableBindingsLength;
     private final IExpression body;
-    
+
     public ILambda(int[] inheritedVariableIds, int arity,
             int variableBindingsLength, IExpression body) {
         this.inheritedVariableIds = inheritedVariableIds;
@@ -20,7 +240,6 @@ public class ILambda implements IExpression {
         this.body = body;
     }
 
-    @SuppressWarnings("rawtypes")
     @Override
     public Object execute(Object[] variableBindings) {
         final Object[] inheritedVariableBindings = new Object[inheritedVariableIds.length];
@@ -28,100 +247,18 @@ public class ILambda implements IExpression {
             inheritedVariableBindings[i] = variableBindings[inheritedVariableIds[i]];
         switch(arity) {
         case 1:
-            return new FunctionImpl1() {
-                @Override
-                public Object apply(Object param0) {
-                    Object[] newVariableBindings = new Object[variableBindingsLength];
-                    int i = 0;;
-                    for(;i < inheritedVariableBindings.length;++i)
-                        newVariableBindings[i] = inheritedVariableBindings[i];
-                    newVariableBindings[i] = param0;
-                    return body.execute(newVariableBindings);
-                }
-                
-                @Override
-                public String toString() {
-                       return ILambda.this.toString(inheritedVariableBindings);
-                }
-            };
+            return new Arity1Func(inheritedVariableBindings);
         case 2:
-            return new FunctionImpl2() {
-                @Override
-                public Object apply(Object param0, Object param1) {
-                    Object[] newVariableBindings = new Object[variableBindingsLength];
-                    int i = 0;;
-                    for(;i < inheritedVariableBindings.length;++i)
-                        newVariableBindings[i] = inheritedVariableBindings[i];
-                    newVariableBindings[i++] = param0;
-                    newVariableBindings[i] = param1;
-                    return body.execute(newVariableBindings);
-                }
-                
-                @Override
-                public String toString() {
-                       return ILambda.this.toString(inheritedVariableBindings);
-                }
-            };
+            return new Arity2Func(inheritedVariableBindings);
         case 3:
-            return new FunctionImpl3() {
-                @Override
-                public Object apply(Object param0, Object param1, Object param2) {
-                    Object[] newVariableBindings = new Object[variableBindingsLength];
-                    int i = 0;;
-                    for(;i < inheritedVariableBindings.length;++i)
-                        newVariableBindings[i] = inheritedVariableBindings[i];
-                    newVariableBindings[i++] = param0;
-                    newVariableBindings[i++] = param1;
-                    newVariableBindings[i] = param2;
-                    return body.execute(newVariableBindings);
-                }
-                
-                @Override
-                public String toString() {
-                       return ILambda.this.toString(inheritedVariableBindings);
-                }
-            };
+            return new Arity3Func(inheritedVariableBindings);
         case 4:
-            return new FunctionImpl4() {
-                @Override
-                public Object apply(Object param0, Object param1, Object param2, Object param3) {
-                    Object[] newVariableBindings = new Object[variableBindingsLength];
-                    int i = 0;;
-                    for(;i < inheritedVariableBindings.length;++i)
-                        newVariableBindings[i] = inheritedVariableBindings[i];
-                    newVariableBindings[i++] = param0;
-                    newVariableBindings[i++] = param1;
-                    newVariableBindings[i++] = param2;
-                    newVariableBindings[i] = param3;
-                    return body.execute(newVariableBindings);
-                }
-                
-                @Override
-                public String toString() {
-                       return ILambda.this.toString(inheritedVariableBindings);
-                }
-            };
+            return new Arity4Func(inheritedVariableBindings);
         default:
-            return new FunctionImplN(arity) {
-                @Override
-                public Object doApply(Object... ps) {
-                    Object[] newVariableBindings = new Object[variableBindingsLength];
-                    int i = 0;;
-                    for(;i < inheritedVariableBindings.length;++i)
-                        newVariableBindings[i] = inheritedVariableBindings[i];
-                    for(Object p : ps)
-                        newVariableBindings[i++] = p;
-                    return body.execute(newVariableBindings);
-                }
-                
-                @Override
-                public String toString() {
-                       return ILambda.this.toString(inheritedVariableBindings);
-                }
-            };
+            return new ArityNFunc(inheritedVariableBindings);
         }
     }
-    
+
     @Override
     public String toString() {
         StringBuilder b = new StringBuilder();
@@ -136,22 +273,22 @@ public class ILambda implements IExpression {
         b.append(')');
         return b.toString();
     }
-    
+
     public String toString(Object[] variableBindings) {
-       StringBuilder sb = new StringBuilder();
-       appendVariableBindings(sb, variableBindings);
-       sb.append(this.toString());
-       return sb.toString();
+        StringBuilder sb = new StringBuilder();
+        appendVariableBindings(sb, variableBindings);
+        sb.append(this.toString());
+        return sb.toString();
     }
-    
+
     private static void appendVariableBindings(StringBuilder sb, Object[] variableBindings) {
-       if (variableBindings.length > 0) {
-               sb.append("(let {");
-               for(int i = 0; i < variableBindings.length; i++) {
-                       if (i > 0) sb.append("; ");
-                       sb.append("v").append(i).append("=").append(variableBindings[i].toString());
-               }
-               sb.append("} in ");
-       }       
+        if (variableBindings.length > 0) {
+            sb.append("(let {");
+            for(int i = 0; i < variableBindings.length; i++) {
+                if (i > 0) sb.append("; ");
+                sb.append("v").append(i).append("=").append(variableBindings[i].toString());
+            }
+            sb.append("} in ");
+        }      
     }
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java
new file mode 100644 (file)
index 0000000..25d14e2
--- /dev/null
@@ -0,0 +1,36 @@
+package org.simantics.scl.compiler.internal.parsing.declarations;
+
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
+
+
+
+public class DModuleHeader extends DeclarationAst {
+    public final FieldAssignment[] fields;
+    
+    public DModuleHeader(FieldAssignment[] fields) {
+        this.fields = fields;
+    }
+
+    @Override
+    public void toString(int indentation, StringBuilder b) {
+        for(int i=0;i<indentation;++i) b.append("    ");
+        b.append("module {");
+        ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+        boolean first = true;
+        for(FieldAssignment field : fields) {
+            if(first)
+                first = false;
+            else
+                b.append(',');
+            b.append('\n');
+            for(int i=0;i<=indentation;++i) b.append("    ");
+            b.append(field.name);
+            b.append(" = ");
+            field.value.accept(visitor);
+        }
+        b.append('\n');
+        for(int i=0;i<indentation;++i) b.append("    ");
+        b.append('}');
+    }
+}
index 6bcffa14789b96542b16cccf2a5bbf8d7163f0c7..8ff94fd4b8f4db278f4f79f3b57010219f362a90 100644 (file)
@@ -33,7 +33,8 @@ declarations
     ;
 
 declaration
-    = var (COMMA var)* HASTYPE type                          # TypeAnnotation
+    = MODULE LBRACE (field (COMMA field)*)? RBRACE           # ModuleHeader
+    | var (COMMA var)* HASTYPE type                          # TypeAnnotation
     | bexp rhs                                               # ValueDefinition
     | DATA ID+ (EQUALS constructor (BAR constructor)*)?      # DataDefinition
     | TYPE ID+ EQUALS type                                   # TypeDefinition
index e6534c5527cdbda79d88ba7cd2e43c9815041c62..da6ec2969c2b796a91d045b6977a1de2f7b867bd 100644 (file)
Binary files a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat and b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat differ
index 6c8ee5be9c0de160fd7123f0027c9dc5a9ff18d4..362bc51420da61eccbac64be9e5165a84bf88cf9 100644 (file)
@@ -13,18 +13,18 @@ public abstract class SCLParser {
     public static final boolean TRACE = false;
 
     private static final int INITIAL_CAPACITY = 16;
-    private static final int STATE_COUNT = 344;
-    private static final int TERMINAL_COUNT = 82;
+    private static final int STATE_COUNT = 349;
+    private static final int TERMINAL_COUNT = 83;
     private static final int NONTERMINAL_COUNT = 51;
-    private static final int PRODUCT_COUNT = 132;
+    private static final int PRODUCT_COUNT = 133;
     
     private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];
     private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];
-    private static final short[] ACTION_TABLE = new short[6120];
-    private static final int[] ERROR_TABLE = new int[882];
+    private static final short[] ACTION_TABLE = new short[6396];
+    private static final int[] ERROR_TABLE = new int[906];
     private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];
     private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];
-    private static final short[] GOTO_TABLE = new short[1829];
+    private static final short[] GOTO_TABLE = new short[1652];
     private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];
 
     private static final short STATE_MASK = (short)0x0fff;
@@ -38,6 +38,7 @@ public abstract class SCLParser {
         "SEMICOLON",
         "LBRACE",
         "RBRACE",
+        "MODULE",
         "COMMA",
         "HASTYPE",
         "DATA",
@@ -130,6 +131,7 @@ public abstract class SCLParser {
         "command",
         "statement",
         "declarations",
+        "field",
         "var",
         "bexp",
         "rhs",
@@ -156,7 +158,6 @@ public abstract class SCLParser {
         "stringLiteral",
         "symbolWithoutMinus",
         "listQualifier",
-        "field",
         "chrQuery",
         "verboseChrQuery",
         "caseRhs",
@@ -392,19 +393,19 @@ public abstract class SCLParser {
         return parse(0);
     }
     public Object parseCommands() {
-        return parse(329);
+        return parse(334);
     }
     public Object parseImport() {
-        return parse(336);
+        return parse(341);
     }
     public Object parseType() {
-        return parse(338);
+        return parse(343);
     }
     public Object parseExp() {
-        return parse(340);
+        return parse(345);
     }
     public Object parseEquationBlock() {
-        return parse(342);
+        return parse(347);
     }
 
 
@@ -428,240 +429,242 @@ public abstract class SCLParser {
         case 7:
             return reduceEquationBlock();
         case 8:
-            return reduceTypeAnnotation();
+            return reduceModuleHeader();
         case 9:
-            return reduceValueDefinition();
+            return reduceTypeAnnotation();
         case 10:
-            return reduceDataDefinition();
+            return reduceValueDefinition();
         case 11:
-            return reduceTypeDefinition();
+            return reduceDataDefinition();
         case 12:
-            return reduceClassDefinition();
+            return reduceTypeDefinition();
         case 13:
-            return reduceInstanceDefinition();
+            return reduceClassDefinition();
         case 14:
-            return reduceDerivingInstanceDefinition();
+            return reduceInstanceDefinition();
         case 15:
-            return reduceDocumentationString();
+            return reduceDerivingInstanceDefinition();
         case 16:
-            return reduceAnnotation();
+            return reduceDocumentationString();
         case 17:
-            return reducePrecedenceDefinition();
+            return reduceAnnotation();
         case 18:
-            return reduceJustImport();
+            return reducePrecedenceDefinition();
         case 19:
-            return reduceImportJava();
+            return reduceJustImport();
         case 20:
-            return reduceEffectDefinition();
+            return reduceImportJava();
         case 21:
-            return reduceRuleDefinition();
+            return reduceEffectDefinition();
         case 22:
-            return reduceMappingRelationDefinition();
+            return reduceRuleDefinition();
         case 23:
-            return reduceRelationDefinition();
+            return reduceMappingRelationDefinition();
         case 24:
-            return reduceStatementCommand();
+            return reduceRelationDefinition();
         case 25:
-            return reduceImportCommand();
+            return reduceStatementCommand();
         case 26:
-            return reduceGuardStatement();
+            return reduceImportCommand();
         case 27:
-            return reduceLetStatement();
+            return reduceGuardStatement();
         case 28:
-            return reduceBindStatement();
+            return reduceLetStatement();
         case 29:
-            return reduceRuleStatement();
+            return reduceBindStatement();
         case 30:
-            return reduceCHRStatement();
+            return reduceRuleStatement();
         case 31:
-            return reduceVerboseCHRStatement();
+            return reduceCHRStatement();
         case 32:
-            return reduceConstraintStatement();
+            return reduceVerboseCHRStatement();
         case 33:
-            return reduceDeclarations();
+            return reduceConstraintStatement();
         case 34:
-            return reduceVarId();
+            return reduceDeclarations();
         case 35:
-            return reduceEscapedSymbol();
+            return reduceField();
         case 36:
-            return reduceTupleConstructor();
+            return reduceFieldShorthand();
         case 37:
-            return reduceBinary();
+            return reduceVarId();
         case 38:
-            return reduceSimpleRhs();
+            return reduceEscapedSymbol();
         case 39:
-            return reduceGuardedRhs();
+            return reduceTupleConstructor();
         case 40:
-            return reduceConstructor();
+            return reduceBinary();
         case 41:
-            return reduceRecordConstructor();
+            return reduceSimpleRhs();
         case 42:
-            return reduceContext();
+            return reduceGuardedRhs();
         case 43:
-            return reduceFundeps();
+            return reduceConstructor();
         case 44:
-            return reduceTypeVar();
+            return reduceRecordConstructor();
         case 45:
-            return reduceTupleType();
+            return reduceContext();
         case 46:
-            return reduceListType();
+            return reduceFundeps();
         case 47:
-            return reduceListTypeConstructor();
+            return reduceTypeVar();
         case 48:
-            return reduceTupleTypeConstructor();
+            return reduceTupleType();
         case 49:
-            return reduceLambda();
+            return reduceListType();
         case 50:
-            return reduceLambdaMatch();
+            return reduceListTypeConstructor();
         case 51:
-            return reduceLet();
+            return reduceTupleTypeConstructor();
         case 52:
-            return reduceIf();
+            return reduceLambda();
         case 53:
-            return reduceMatch();
+            return reduceLambdaMatch();
         case 54:
-            return reduceDo();
+            return reduceLet();
         case 55:
-            return reduceSelect();
+            return reduceIf();
         case 56:
-            return reduceEnforce();
+            return reduceMatch();
         case 57:
-            return reduceVar();
+            return reduceDo();
         case 58:
-            return reduceHashedId();
+            return reduceSelect();
         case 59:
-            return reduceBlank();
+            return reduceEnforce();
         case 60:
-            return reduceInteger();
+            return reduceVar();
         case 61:
-            return reduceFloat();
+            return reduceHashedId();
         case 62:
-            return reduceString();
+            return reduceBlank();
         case 63:
-            return reduceChar();
+            return reduceInteger();
         case 64:
-            return reduceTuple();
+            return reduceFloat();
         case 65:
-            return reduceViewPattern();
+            return reduceString();
         case 66:
-            return reduceRightSection();
+            return reduceChar();
         case 67:
-            return reduceLeftSection();
+            return reduceTuple();
         case 68:
-            return reduceListLiteral();
+            return reduceViewPattern();
         case 69:
-            return reduceRange();
+            return reduceRightSection();
         case 70:
-            return reduceListComprehension();
+            return reduceLeftSection();
         case 71:
-            return reduceAs();
+            return reduceListLiteral();
         case 72:
-            return reduceRecord();
+            return reduceRange();
         case 73:
-            return reduceTransformation();
+            return reduceListComprehension();
         case 74:
-            return reduceEq();
+            return reduceAs();
         case 75:
-            return reduceRuleDeclarations();
+            return reduceRecord();
         case 76:
-            return reduceImportShowing();
+            return reduceTransformation();
         case 77:
-            return reduceImportHiding();
+            return reduceEq();
         case 78:
-            return reduceImportValueItem();
+            return reduceRuleDeclarations();
         case 79:
-            return reduceFieldDescription();
+            return reduceImportShowing();
         case 80:
-            return reduceStatements();
+            return reduceImportHiding();
         case 81:
-            return reduceGuardedExpEq();
+            return reduceImportValueItem();
         case 82:
-            return reduceFundep();
+            return reduceFieldDescription();
         case 83:
-            return reduceQueryRuleDeclaration();
+            return reduceStatements();
         case 84:
-            return reduceAnnotation();
+            return reduceGuardedExpEq();
         case 85:
-            return reduceGuardQuery();
+            return reduceFundep();
         case 86:
-            return reduceEqualsQuery();
+            return reduceQueryRuleDeclaration();
         case 87:
-            return reduceBindQuery();
+            return reduceAnnotation();
         case 88:
-            return reduceCompositeQuery();
+            return reduceGuardQuery();
         case 89:
-            return reduceQueryBlock();
+            return reduceEqualsQuery();
         case 90:
-            return reduceApply();
+            return reduceBindQuery();
         case 91:
-            return reduceSymbol();
+            return reduceCompositeQuery();
         case 92:
-            return reduceEscapedId();
+            return reduceQueryBlock();
         case 93:
-            return reduceMinus();
+            return reduceApply();
         case 94:
-            return reduceLess();
+            return reduceSymbol();
         case 95:
-            return reduceGreater();
+            return reduceEscapedId();
         case 96:
-            return reduceDot();
+            return reduceMinus();
         case 97:
-            return reduceFieldAccess();
+            return reduceLess();
         case 98:
-            return reduceIdAccessor();
+            return reduceGreater();
         case 99:
-            return reduceStringAccessor();
+            return reduceDot();
         case 100:
-            return reduceExpAccessor();
+            return reduceFieldAccess();
         case 101:
-            return reduceCase();
+            return reduceIdAccessor();
         case 102:
-            return reduceStringLiteral();
+            return reduceStringAccessor();
         case 103:
-            return reduceSymbol();
+            return reduceExpAccessor();
         case 104:
-            return reduceEscapedId();
+            return reduceCase();
         case 105:
-            return reduceLess();
+            return reduceStringLiteral();
         case 106:
-            return reduceGreater();
+            return reduceSymbol();
         case 107:
-            return reduceDot();
+            return reduceEscapedId();
         case 108:
-            return reduceGuardQualifier();
+            return reduceLess();
         case 109:
-            return reduceLetQualifier();
+            return reduceGreater();
         case 110:
-            return reduceBindQualifier();
+            return reduceDot();
         case 111:
-            return reduceThenQualifier();
+            return reduceGuardQualifier();
         case 112:
-            return reduceField();
+            return reduceLetQualifier();
         case 113:
-            return reduceFieldShorthand();
+            return reduceBindQualifier();
         case 114:
-            return reduceCHRQuery();
+            return reduceThenQualifier();
         case 115:
-            return reduceVerboseCHRQuery();
+            return reduceCHRQuery();
         case 116:
-            return reduceSimpleCaseRhs();
+            return reduceVerboseCHRQuery();
         case 117:
-            return reduceGuardedCaseRhs();
+            return reduceSimpleCaseRhs();
         case 118:
-            return reduceGuardedExpArrow();
+            return reduceGuardedCaseRhs();
         case 119:
-            return reduceGuardEquation();
+            return reduceGuardedExpArrow();
         case 120:
-            return reduceBasicEquation();
+            return reduceGuardEquation();
         case 121:
-            return reduceEffect();
+            return reduceBasicEquation();
         case 122:
-            return reduceJustEtype();
+            return reduceEffect();
         case 123:
-            return reduceForAll();
+            return reduceJustEtype();
         case 124:
-            return reduceApplyType();
+            return reduceForAll();
         case 125:
+            return reduceApplyType();
+        case 126:
             return reduceDummy();
 
         default:
@@ -714,6 +717,10 @@ public abstract class SCLParser {
      * equationBlock ::= (equation (SEMICOLON equation)&#42;)?
      */
     protected abstract Object reduceEquationBlock();
+    /**
+     * declaration ::= MODULE LBRACE (field (COMMA field)&#42;)? RBRACE
+     */
+    protected abstract Object reduceModuleHeader();
     /**
      * declaration ::= (var COMMA)&#42; var HASTYPE type
      */
@@ -818,6 +825,14 @@ public abstract class SCLParser {
      * declarations ::= LBRACE (declaration (SEMICOLON (declaration SEMICOLON)&#42; declaration)?)? RBRACE
      */
     protected abstract Object reduceDeclarations();
+    /**
+     * field ::= ID EQUALS exp
+     */
+    protected abstract Object reduceField();
+    /**
+     * field ::= ID
+     */
+    protected abstract Object reduceFieldShorthand();
     /**
      * var ::= ID
      */
@@ -1106,14 +1121,6 @@ public abstract class SCLParser {
      * listQualifier ::= THEN exp (BY exp)?
      */
     protected abstract Object reduceThenQualifier();
-    /**
-     * field ::= ID EQUALS exp
-     */
-    protected abstract Object reduceField();
-    /**
-     * field ::= ID
-     */
-    protected abstract Object reduceFieldShorthand();
     /**
      * chrQuery ::= (listQualifier COMMA)&#42; listQualifier
      */
index 5498b16b5f0552df54669752cd807e6dde64a53b..90c801403c859ab2218b47000daf86ceb8851bd7 100644 (file)
@@ -87,6 +87,7 @@ import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
@@ -155,10 +156,22 @@ public class SCLParserImpl extends SCLParser {
     @Override
     protected Object reduceModule() {
         ArrayList<DeclarationAst> declarations = new ArrayList<DeclarationAst>(length()/2+1);
-        for(int i=0;i<length();i+=2)
-            declarations.add((DeclarationAst)get(i));
+        for(int i=0;i<length();i+=2) {
+            DeclarationAst declaration = (DeclarationAst)get(i);
+            if(declaration == null)
+                throw new NullPointerException();
+            declarations.add(declaration);
+        }
         return declarations;
     }
+    
+    @Override
+    protected Object reduceModuleHeader() {
+        FieldAssignment[] fields = new FieldAssignment[length()/2-1];
+        for(int i=0;i<fields.length;++i)
+            fields[i] = (FieldAssignment)get(2+i*2);
+        return new DModuleHeader(fields);
+    }
 
     @Override
     protected Object reduceLocalTypeAnnotation() {
index 002e2d62db11fc399c24aec912b98c593bdb6068..fed87b1bad73910bf8f497f201623f7cc4f35d92 100644 (file)
@@ -2,6 +2,12 @@ package org.simantics.scl.compiler.internal.parsing.parser;
 
 public class SCLParserOptions {
     public static final SCLParserOptions DEFAULT = new SCLParserOptions();
+    public static final SCLParserOptions MODULE_DEFAULT = new SCLParserOptions();
+    
+    static {
+        MODULE_DEFAULT.isModule = true;
+    }
     
     public boolean supportEq;
+    public boolean isModule;
 }
index efc799322b3d37c4220a90de6f8061154d3ace35..9cc1ff27b16a288afb11f138b9d8755a84f642d0 100644 (file)
@@ -57,6 +57,7 @@ public class SCLPostLexer {
     int lineStart = 0;
     boolean firstTokenOfLine = true;
     private SCLParserOptions options;
+    private boolean isFirstToken = true;
             
     {
         indentations.add(0);
@@ -151,6 +152,13 @@ public class SCLPostLexer {
                 }
             }
             firstTokenOfLine = false;
+            if(isFirstToken) {
+                isFirstToken = false;
+                if(symbol.id == SCLTerminals.ID && symbol.text.equals("module") && options != null && options.isModule) {
+                    push(new Token(SCLTerminals.MODULE, symbol.location, symbol.text));
+                    return;
+                }
+            }
         }
         
         switch(symbolId) {
@@ -166,8 +174,8 @@ public class SCLPostLexer {
             return;
         case SCLTerminals.THEN:
             /*for(int tt : indentationTokens.toArray())
-                System.out.print(SCLParser.TERMINAL_NAMES[tt] + " ");
-            System.out.println();*/
+                    System.out.print(SCLParser.TERMINAL_NAMES[tt] + " ");
+                System.out.println();*/
             if(prevTokenId == SCLTerminals.COMMA) {
                 // for list comprehension syntax
                 push(symbol);
index e676b4d482335035311231453363ede2b2683cdc..98ef910f375e417c1668d175026180fed0a9ab7f 100644 (file)
@@ -4,83 +4,84 @@ public interface SCLTerminals {
     public static final int SEMICOLON = 0;
     public static final int LBRACE = 1;
     public static final int RBRACE = 2;
-    public static final int COMMA = 3;
-    public static final int HASTYPE = 4;
-    public static final int DATA = 5;
-    public static final int ID = 6;
-    public static final int EQUALS = 7;
-    public static final int BAR = 8;
-    public static final int TYPE = 9;
-    public static final int CLASS = 10;
-    public static final int WHERE = 11;
-    public static final int INSTANCE = 12;
-    public static final int DERIVING = 13;
-    public static final int BEGIN_STRING = 14;
-    public static final int END_STRING = 15;
-    public static final int ANNOTATION_ID = 16;
-    public static final int INFIX = 17;
-    public static final int INFIXL = 18;
-    public static final int INFIXR = 19;
-    public static final int INTEGER = 20;
-    public static final int IMPORTJAVA = 21;
-    public static final int EFFECT = 22;
-    public static final int RULE = 23;
-    public static final int ABSTRACT_RULE = 24;
-    public static final int EXTENDS = 25;
-    public static final int MAPPING_RELATION = 26;
-    public static final int FOLLOWS = 27;
-    public static final int IMPORT = 28;
-    public static final int INCLUDE = 29;
-    public static final int AS = 30;
-    public static final int LPAREN = 31;
-    public static final int RPAREN = 32;
-    public static final int HIDING = 33;
-    public static final int ARROW = 34;
-    public static final int COLON = 35;
-    public static final int WITH = 36;
-    public static final int MINUS = 37;
-    public static final int SYMBOL = 38;
-    public static final int LESS = 39;
-    public static final int GREATER = 40;
-    public static final int SEPARATED_DOT = 41;
-    public static final int ESCAPED_ID = 42;
-    public static final int LAMBDA = 43;
-    public static final int LAMBDA_MATCH = 44;
-    public static final int LET = 45;
-    public static final int IF = 46;
-    public static final int MATCH = 47;
-    public static final int DO = 48;
-    public static final int MDO = 49;
-    public static final int ENFORCE = 50;
-    public static final int BLANK = 51;
-    public static final int FLOAT = 52;
-    public static final int LBRACKET = 53;
-    public static final int ESCAPED_SYMBOL = 54;
-    public static final int CHAR = 55;
-    public static final int WHEN = 56;
-    public static final int ATTACHED_HASH = 57;
-    public static final int SELECT = 58;
-    public static final int SELECT_FIRST = 59;
-    public static final int SELECT_DISTINCT = 60;
-    public static final int TRANSFORMATION = 61;
-    public static final int EQ = 62;
-    public static final int ATTACHED_DOT = 63;
-    public static final int IN = 64;
-    public static final int THEN = 65;
-    public static final int ELSE = 66;
-    public static final int RBRACKET = 67;
-    public static final int DOTDOT = 68;
-    public static final int AT = 69;
-    public static final int SUSPEND_STRING = 70;
-    public static final int CONTINUE_STRING = 71;
-    public static final int BINDS = 72;
-    public static final int IMPLIES = 73;
-    public static final int THEN_AFTER_WHEN = 74;
-    public static final int CONSTRAINT = 75;
-    public static final int BY = 76;
-    public static final int QUERY_OP = 77;
-    public static final int FORALL = 78;
-    public static final int COMMENT = 79;
-    public static final int EOL = 80;
-    public static final int EOF = 81;
+    public static final int MODULE = 3;
+    public static final int COMMA = 4;
+    public static final int HASTYPE = 5;
+    public static final int DATA = 6;
+    public static final int ID = 7;
+    public static final int EQUALS = 8;
+    public static final int BAR = 9;
+    public static final int TYPE = 10;
+    public static final int CLASS = 11;
+    public static final int WHERE = 12;
+    public static final int INSTANCE = 13;
+    public static final int DERIVING = 14;
+    public static final int BEGIN_STRING = 15;
+    public static final int END_STRING = 16;
+    public static final int ANNOTATION_ID = 17;
+    public static final int INFIX = 18;
+    public static final int INFIXL = 19;
+    public static final int INFIXR = 20;
+    public static final int INTEGER = 21;
+    public static final int IMPORTJAVA = 22;
+    public static final int EFFECT = 23;
+    public static final int RULE = 24;
+    public static final int ABSTRACT_RULE = 25;
+    public static final int EXTENDS = 26;
+    public static final int MAPPING_RELATION = 27;
+    public static final int FOLLOWS = 28;
+    public static final int IMPORT = 29;
+    public static final int INCLUDE = 30;
+    public static final int AS = 31;
+    public static final int LPAREN = 32;
+    public static final int RPAREN = 33;
+    public static final int HIDING = 34;
+    public static final int ARROW = 35;
+    public static final int COLON = 36;
+    public static final int WITH = 37;
+    public static final int MINUS = 38;
+    public static final int SYMBOL = 39;
+    public static final int LESS = 40;
+    public static final int GREATER = 41;
+    public static final int SEPARATED_DOT = 42;
+    public static final int ESCAPED_ID = 43;
+    public static final int LAMBDA = 44;
+    public static final int LAMBDA_MATCH = 45;
+    public static final int LET = 46;
+    public static final int IF = 47;
+    public static final int MATCH = 48;
+    public static final int DO = 49;
+    public static final int MDO = 50;
+    public static final int ENFORCE = 51;
+    public static final int BLANK = 52;
+    public static final int FLOAT = 53;
+    public static final int LBRACKET = 54;
+    public static final int ESCAPED_SYMBOL = 55;
+    public static final int CHAR = 56;
+    public static final int WHEN = 57;
+    public static final int ATTACHED_HASH = 58;
+    public static final int SELECT = 59;
+    public static final int SELECT_FIRST = 60;
+    public static final int SELECT_DISTINCT = 61;
+    public static final int TRANSFORMATION = 62;
+    public static final int EQ = 63;
+    public static final int ATTACHED_DOT = 64;
+    public static final int IN = 65;
+    public static final int THEN = 66;
+    public static final int ELSE = 67;
+    public static final int RBRACKET = 68;
+    public static final int DOTDOT = 69;
+    public static final int AT = 70;
+    public static final int SUSPEND_STRING = 71;
+    public static final int CONTINUE_STRING = 72;
+    public static final int BINDS = 73;
+    public static final int IMPLIES = 74;
+    public static final int THEN_AFTER_WHEN = 75;
+    public static final int CONSTRAINT = 76;
+    public static final int BY = 77;
+    public static final int QUERY_OP = 78;
+    public static final int FORALL = 79;
+    public static final int COMMENT = 80;
+    public static final int EOL = 81;
+    public static final int EOF = 82;
 }
index a8b51a8be96cad3a0aa1933758e89cc4201707bf..697e64ef805e1eafc53300cb37c49c79c66b4e8e 100644 (file)
@@ -45,6 +45,7 @@ public class ConcreteModule implements Module {
     CompilationError[] warnings = CompilationError.EMPTY_ARRAY;
     
     Map<String, byte[]> classes = Collections.emptyMap();
+    ClassLoader parentClassLoader;
     ModuleInitializer moduleInitializer;
 
     protected Documentation documentation;
@@ -278,4 +279,15 @@ public class ConcreteModule implements Module {
     public CompilationError[] getWarnings() {
         return warnings;
     }
+    
+    @Override
+    public ClassLoader getParentClassLoader() {
+        return parentClassLoader;
+    }
+    
+    public void setParentClassLoader(ClassLoader parentClassLoader) {
+        if(parentClassLoader == null)
+            throw new NullPointerException();
+        this.parentClassLoader = parentClassLoader;
+    }
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/InvalidModulePathException.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/InvalidModulePathException.java
new file mode 100644 (file)
index 0000000..5fe4677
--- /dev/null
@@ -0,0 +1,11 @@
+package org.simantics.scl.compiler.module;
+
+public class InvalidModulePathException extends Exception {
+
+       private static final long serialVersionUID = 4981982587509793105L;      
+       
+       public InvalidModulePathException(String message) {
+               super(message);
+       }
+
+}
\ No newline at end of file
index 180509521312ca6e7bb014ec0d99e8ba7ab015b2..6f13ed426940e11a2d59e949a670c1cedb7a7d6f 100644 (file)
@@ -54,5 +54,5 @@ public interface Module {
     void dispose();
 
     CompilationError[] getWarnings();
-    
+    ClassLoader getParentClassLoader();
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ModuleUtils.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ModuleUtils.java
new file mode 100644 (file)
index 0000000..f5ae62a
--- /dev/null
@@ -0,0 +1,30 @@
+package org.simantics.scl.compiler.module;
+
+public class ModuleUtils {
+    public static String resolveAbsolutePath(String moduleName, String relativeModuleName) throws InvalidModulePathException {
+        if (relativeModuleName.startsWith(".")) {
+               String originalRelativeModuleName = relativeModuleName;
+               int p = moduleName.lastIndexOf('/');
+               String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
+               while(relativeModuleName.startsWith(".")) {
+                   if(relativeModuleName.startsWith("./")) {
+                       relativeModuleName = relativeModuleName.substring(2);
+                   }
+                   else if(relativeModuleName.startsWith("../")) {
+                       relativeModuleName = relativeModuleName.substring(3);
+                       if(parentPackage.isEmpty()) {
+                           throw new InvalidModulePathException("Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
+                       }
+                       p = parentPackage.lastIndexOf('/');
+                       parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
+                   }
+                   else {
+                       throw new InvalidModulePathException("Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
+                   }
+               }
+               return parentPackage + "/" + relativeModuleName;
+        } else {
+               return relativeModuleName;
+        }
+    }
+}
index 7170b992b41d87be51e0e615d4723985bb03478e..40c69f4348861e2d4bd58877d762f4677d90c7f1 100644 (file)
@@ -173,7 +173,7 @@ public class ModuleRepository {
                         if(parentModule != null)
                             parentModules.add(parentModule);
                     }*/
-                    RuntimeModule rm = new RuntimeModule(module, parentModules, source.getClassLoader());
+                    RuntimeModule rm = new RuntimeModule(module, parentModules, module.getParentClassLoader());
                     ModuleInitializer initializer = module.getModuleInitializer();
                     if(initializer != null)
                         try {
index 2415e652074384c500ee8a0cc0914f0eb22f568a..93ecb2f1721adbb86b649ef58395cd5a813accad 100644 (file)
@@ -209,6 +209,8 @@ public class RuntimeModule {
     
     public RuntimeModule(Module module, RuntimeModuleMap parentModuleMap,
             ClassLoader parentClassLoader) {
+        if(parentClassLoader == null)
+            throw new NullPointerException();
         this.module = module;
         this.parentModuleMap = parentModuleMap;
         this.classLoader = new ModuleClassLoader(parentClassLoader);
index 4f22022e5f46cd6ba5cb60767fbbb05f425f86bf..9a6f4c97fb07c33689e21885a1a641d4bdcadf01 100644 (file)
@@ -11,6 +11,7 @@ import org.simantics.scl.compiler.errors.Failable;
 import org.simantics.scl.compiler.errors.Failure;
 import org.simantics.scl.compiler.errors.Success;
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
 import org.simantics.scl.compiler.internal.codegen.types.RuntimeJavaReferenceValidator;
 import org.simantics.scl.compiler.module.ImportDeclaration;
 import org.simantics.scl.compiler.module.Module;
@@ -80,7 +81,7 @@ public abstract class TextualModuleSource implements ModuleSource {
     @SuppressWarnings("unchecked")
     @Override
     public Failable<Module> compileModule(final ModuleRepository environment, final UpdateListener listener, ModuleCompilationOptions options) {
-        SCLCompiler compiler = new SCLCompiler(options);
+        SCLCompiler compiler = new SCLCompiler(options, getJavaReferenceValidatorFactory());
         try {
             compiler.addSource(getSourceReader(listener));
             compiler.compile(
@@ -88,8 +89,7 @@ public abstract class TextualModuleSource implements ModuleSource {
                             environment, 
                             getBuiltinImports(listener),
                             listener),
-                    moduleName,
-                    getJavaReferenceValidator());
+                    moduleName);
             if(compiler.getErrorLog().hasNoErrors())
                 return new Success<Module>(compiler.getModule());
             else {
@@ -102,6 +102,21 @@ public abstract class TextualModuleSource implements ModuleSource {
         }
     }
     
+    public JavaReferenceValidatorFactory getJavaReferenceValidatorFactory() {
+        return new JavaReferenceValidatorFactory() {
+            
+            @Override
+            public JavaReferenceValidator<Object, Object, Object, Object> getJavaReferenceValidator(String context) {
+                return (JavaReferenceValidator<Object, Object, Object, Object>)TextualModuleSource.this.getJavaReferenceValidator();
+            }
+            
+            @Override
+            public JavaReferenceValidator<Object, Object, Object, Object> getDefaultJavaReferenceValidator() {
+                return (JavaReferenceValidator<Object, Object, Object, Object>)TextualModuleSource.this.getJavaReferenceValidator();
+            }
+        };
+    }
+
     @Override
     public double getPriority() {
         return priority;
index 4e1f00e8d4aadeca52094adb3e8dc378a2deefed..65a68a712106fb78480f23e4951a35c2f6e129a3 100644 (file)
@@ -3,6 +3,7 @@ package org.simantics.scl.compiler.source.repository;
 import org.osgi.service.component.annotations.Component;
 import org.simantics.scl.compiler.elaboration.java.Builtins;
 import org.simantics.scl.compiler.elaboration.java.JavaModule;
+import org.simantics.scl.compiler.elaboration.java.LoggingModule;
 import org.simantics.scl.compiler.elaboration.java.MinigraphModule;
 
 @Component
@@ -10,6 +11,7 @@ public class BuiltinModuleSourceRepository extends MapModuleSourceRepository imp
     public BuiltinModuleSourceRepository() {
         super(Builtins.INSTANCE,
                 JavaModule.INSTANCE,
-                MinigraphModule.INSTANCE);
+                MinigraphModule.INSTANCE,
+                new LoggingModule());
     }
 }
index 280f6ebbf7286397a867b8f96e67fdfbc9c8df04..3d71ae5143a577bf7ec7aeafa3f863b4b978260b 100644 (file)
@@ -256,6 +256,22 @@ importJava "org.simantics.db.common.utils.OrderedSetUtils" where
 importJava "org.simantics.db.common.utils.ListUtils" where
     @JavaName toList
     elementsOfList :: Resource -> <ReadGraph> [Resource]
+    
+    @JavaName create
+    createList :: [Resource] -> <WriteGraph> Resource
+    
+    @javaName insertBack
+    insertBack :: Resource -> [Resource] -> <WriteGraph> ()
+    
+    @javaName removeElement
+    removeElement :: Resource -> Resource -> <WriteGraph> Boolean
+    
+    @javaName swapWithPrevious
+    swapWithPrevious :: Resource -> Resource -> <WriteGraph> Boolean
+
+    @javaName swapWithNext
+    swapWithNext :: Resource -> Resource -> <WriteGraph> Boolean
+
 
 importJava "org.simantics.db.common.utils.CommonDBUtils" where
     isParent :: Resource -> Resource -> <ReadGraph> Boolean
@@ -302,6 +318,11 @@ importJava "org.simantics.scl.db.SCLFunctions" where
     unaryQuery :: (a -> <ReadGraph,e> b) -> a -> <ReadGraph> b
     unaryQueryCached :: (a -> <ReadGraph,e> b) -> a -> <ReadGraph> b
 
+    "Makes a new read request with given procedure for calculating the result. The request is cached only if the current request is listened."
+    subquery :: (<ReadGraph,Proc> a) -> <ReadGraph,Proc> a
+    "Makes a new read request with given procedure for calculating the result. The request is always cached."
+    subqueryC :: (<ReadGraph,Proc> a) -> <ReadGraph,Proc> a
+
 importJava "org.simantics.db.layer0.util.Layer0Utils" where
     undo :: () -> <Proc> String
     undoOperations :: Integer -> <Proc> String
@@ -312,6 +333,8 @@ importJava "org.simantics.db.layer0.util.Layer0Utils" where
     sortByCluster :: [a] -> (a->Resource) -> <ReadGraph> [a]
     makeSynchronous :: Boolean -> <ReadGraph> ()
     listOntologies :: () -> <ReadGraph> [Resource]
+    emptyTrashBin :: () -> <Proc> ()
+    purgeDatabase :: () -> <Proc> ()
 
     @private
     @JavaName copyTo
index d96dacdfdb4de0b8793060c034c83000eadc0cf6..721d52b15696fe5748947daeec249671006c586c 100644 (file)
@@ -332,13 +332,13 @@ Example:
 """
 
 modelVariableOfVariable :: Variable -> <ReadGraph> Variable     
-modelVariableOfVariable var = variable $ uriOf $ toResource $ modelOfVariable var
+modelVariableOfVariable var = variable $ uriOf $ modelOfVariable var
 
 uniqueChild :: Model -> Resource -> String -> <ReadGraph> Variable
 uniqueChild model typet childName = do
     typeName = DB.nameOf typet
     query = "Types: " + typeName + " AND Name: " + childName
-    moduleResources = searchByQuery (toResource model) query
+    moduleResources = searchByQuery model query
     variable $ uriOf $ moduleResources ! 0
 
 """
index 77f6a6f11ee1e298c1fa104d3fa0b6ef4f97ff3b..9b4d6b8ac92ec90d5c3970285efbe15d7550c008 100644 (file)
@@ -263,4 +263,51 @@ public class SCLFunctions {
        return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.<Object>instance());
     }
     
+
+    private static class Subquery implements Read<Object> {
+        Function q;
+
+        public Subquery(Function q) {
+            this.q = q;
+        }
+
+        @Override
+        public Object perform(ReadGraph graph) throws DatabaseException {
+            SCLContext sclContext = SCLContext.getCurrent();
+            Object oldGraph = sclContext.put("graph", graph);
+            try {
+                return q.apply(Tuple0.INSTANCE);
+            } catch (Throwable e) {
+                if(e instanceof DatabaseException)
+                    throw (DatabaseException)e;
+                else
+                    throw new DatabaseException(e);
+            } finally {
+                sclContext.put("graph", oldGraph);
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return q.hashCode();
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if(this == obj)
+                return true;
+            if(obj == null || obj.getClass() != getClass())
+                return false;
+            Subquery other = (Subquery)obj;
+            return q.equals(other.q);
+        }
+    }
+
+    public static Object subquery(ReadGraph graph, Function q) throws DatabaseException {
+        return graph.syncRequest(new Subquery(q));
+    }
+
+    public static Object subqueryC(ReadGraph graph, Function q) throws DatabaseException {
+        return graph.syncRequest(new Subquery(q), TransientCacheAsyncListener.<Object>instance());
+    }
 }
index 244c7463f0d5ade4ba574a373fd13ee9940a99b0..3213cf9b5419e7d501fdba77afd93218babc0c9e 100644 (file)
@@ -15,6 +15,7 @@ import java.util.Arrays;
 import org.eclipse.core.runtime.FileLocator;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.wiring.BundleWiring;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
 import org.simantics.scl.compiler.module.ImportDeclaration;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.EncodedTextualModuleSource;
@@ -161,4 +162,7 @@ public class BundleModuleSource extends EncodedTextualModuleSource implements Up
         }
     }
 
+    public JavaReferenceValidatorFactory getJavaReferenceValidatorFactory() {
+        return new OsgiJavaReferenceValidatorFactory(bundle);
+    }
 }
diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/OsgiJavaReferenceValidatorFactory.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/OsgiJavaReferenceValidatorFactory.java
new file mode 100644 (file)
index 0000000..03524e8
--- /dev/null
@@ -0,0 +1,58 @@
+package org.simantics.scl.osgi.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWiring;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
+import org.simantics.scl.compiler.internal.codegen.types.RuntimeJavaReferenceValidator;
+import org.simantics.scl.compiler.types.Type;
+
+public class OsgiJavaReferenceValidatorFactory implements JavaReferenceValidatorFactory {
+
+    private final Bundle bundle;
+
+    public OsgiJavaReferenceValidatorFactory(Bundle bundle) {
+        this.bundle = bundle;
+    }
+
+    private static ClassLoader getClassLoader(Bundle bundle) {
+        if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))
+            return Type.class.getClassLoader();
+        else {
+            BundleWiring wiring = bundle.adapt(BundleWiring.class);
+            if(wiring != null)
+                return wiring.getClassLoader();
+            throw new InternalCompilerError("Cannot get the class loader for bundle " + bundle.getSymbolicName() + ".");
+        }
+    }
+
+    private static JavaReferenceValidator<Object, Object, Object, Object> getJavaReferenceValidator(Bundle bundle) {
+        if(bundle == null)
+            return null;
+        return (JavaReferenceValidator<Object, Object, Object, Object>)
+                (JavaReferenceValidator<?, ?, ?, ?>)new RuntimeJavaReferenceValidator(getClassLoader(bundle));
+    }
+
+    private static Bundle getBundle(BundleContext bundleContext, String symbolicName) {
+        Bundle result = null;
+        for (Bundle candidate : bundleContext.getBundles())
+            if (candidate.getSymbolicName().equals(symbolicName))
+                if (result == null || result.getVersion().compareTo(candidate.getVersion()) < 0)
+                    result = candidate;
+        return result;
+    }
+    
+    @Override
+    public JavaReferenceValidator<Object, Object, Object, Object> getJavaReferenceValidator(String bundleName) {
+        System.out.println("getJavaReferenceValidator(" + bundleName + ")");
+        return getJavaReferenceValidator(getBundle(bundle.getBundleContext(), bundleName));
+    }
+
+    @Override
+    public JavaReferenceValidator<Object, Object, Object, Object> getDefaultJavaReferenceValidator() {
+        return getJavaReferenceValidator(bundle);
+    }
+
+}
index adf2dee305c3693064d1d2a5893888d589ab8087..2e61986e855103a48022305b764aed0b794a8b34 100644 (file)
@@ -11,9 +11,9 @@ public class GenerateFunctions {
     public static final int MAX_ARITY = 8;
     
     public static final String HEADER =
-            "/**\n"
-          + " * This code is generated in " + GenerateFunctions.class.getName() + ".\n"
-          + " * Do not edit manually!\n"
+            "/**\r\n"
+          + " * This code is generated in " + GenerateFunctions.class.getName() + ".\r\n"
+          + " * Do not edit manually!\r\n"
           + " */" 
             ;
     
@@ -342,6 +342,7 @@ public class GenerateFunctions {
             p.println("            nps[i + " + n + "] = ps[i];");
             p.println("        return f.applyArray(nps);");
             p.println("    }");
+            p.println();
         }
         {
             p.println("    @Override");
@@ -353,6 +354,40 @@ public class GenerateFunctions {
             p.println("        sb.append(\")\");");
             p.println("        return sb.toString();");
             p.println("    }");
+            p.println();
+        }
+        {
+            p.println("    @Override");
+            p.println("    public int hashCode() {");
+            p.println("        int result = f.hashCode();");
+            for(int i=0;i<n;++i)
+                p.println("        result = 31 * result + (p"+i+" == null ? 0 : p"+i+".hashCode());");
+            p.println("        return result;");
+            p.println("    }");
+            p.println();
+        }
+        {
+            p.println("    @Override");
+            p.println("    public boolean equals(Object obj) {");
+            p.println("        if (this == obj)");
+            p.println("            return true;");
+            p.println("        if (obj == null)");
+            p.println("            return false;");
+            p.println("        if (getClass() != obj.getClass())");
+            p.println("            return false;");
+            p.println("        UnsaturatedFunction"+n+" other = (UnsaturatedFunction"+n+") obj;");
+            p.println("        if(!f.equals(other.f))");
+            p.println("            return false;");
+            for(int i=0;i<n;++i) {
+                p.println("        if(p"+i+" == null) {");
+                p.println("            if (other.p"+i+" != null)");
+                p.println("                return false;");
+                p.println("        } else if (!p"+i+".equals(other.p"+i+"))");
+                p.println("            return false;");
+            }
+            p.println("        return true;");
+            p.println("    }");
+            p.println();
         }
         p.println("}");
     }
@@ -361,6 +396,8 @@ public class GenerateFunctions {
         p.println(HEADER);
         p.println("package " + PACKAGE + ";");
         p.println();
+        p.println("import java.util.Arrays;");
+        p.println();
         p.println("@SuppressWarnings(\"all\")");
         p.println("public class UnsaturatedFunctionN implements Function {");
         p.println("    private final Function f;");
@@ -396,6 +433,7 @@ public class GenerateFunctions {
             p.println("        System.arraycopy(ops, 0, nps, ps.length, ops.length);");
             p.println("        return f.applyArray(nps);");
             p.println("    }");
+            p.println();
         }
         {
             p.println("    @Override");
@@ -407,6 +445,28 @@ public class GenerateFunctions {
             p.println("        sb.append(\")\");");
             p.println("        return sb.toString();");
             p.println("    }");
+            p.println();
+        }
+        {
+            p.println("    @Override");
+            p.println("    public int hashCode() {");
+            p.println("        return f.hashCode() + 31 * Arrays.hashCode(ps);");
+            p.println("    }");
+            p.println();
+        }
+        {
+            p.println("    @Override");
+            p.println("    public boolean equals(Object obj) {");
+            p.println("        if (this == obj)");
+            p.println("            return true;");
+            p.println("        if (obj == null)");
+            p.println("            return false;");
+            p.println("        if (getClass() != obj.getClass())");
+            p.println("            return false;");
+            p.println("        UnsaturatedFunctionN other = (UnsaturatedFunctionN) obj;");
+            p.println("        return f.equals(other.f) && Arrays.equals(ps, other.ps);");
+            p.println("    }");
+            p.println();
         }
         p.println("}");
     }
index 2c5966dc40f99a2b38a594b675dd8dc9588bf1bb..c81f8308954e8ee241653b686b8d0bcbeffdaa6c 100644 (file)
@@ -1396,7 +1396,7 @@ instance Show String where
 instance Read String where
     read str = str
     
-@deprecated
+@deprecated "Instead of 'splitString text pattern', write 'split pattern text' (note change in the parameter order)." 
 "`splitString text pattern` splits the string into a list of string where the parts are sepratated in the original list by the given pattern."
 splitString :: String -> String -> [String]
 splitString source pattern = arrayToList $ splitString_ source pattern
index 7149fc63ef9d8d8ddc9256aa9ce4319213a8c924..a5722763551855d4d60525066732ba9943420d8c 100644 (file)
@@ -144,16 +144,17 @@ public class Lists {
     public static Object get(List l, double i) {
         return l.get((int)i);
     }
+
+    private static final FunctionImpl2 BUILD_FUNC = new FunctionImpl2() {
+        @Override
+        public Object apply(Object p0, Object p1) {
+            ((ArrayList)p0).add(p1);
+            return p0;
+        }
+    };
     
     public static List build(Function f) {
-        return (List)f.apply(new ArrayList(),
-                new FunctionImpl2() {
-            @Override
-            public Object apply(Object p0, Object p1) {
-                ((List)p0).add(p1);
-                return p0;
-            }
-        });
+        return (List)f.apply(new ArrayList(), BUILD_FUNC);
     }
     
     public static List range(int from, int to) {
index b3b858236a2b9c017adca1209ea073b4f1499dc9..1dbca0be94f8f223b8d117f7561c228bec085ceb 100644 (file)
@@ -62,6 +62,7 @@ public class UnsaturatedFunction1 implements Function {
             nps[i + 1] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -70,4 +71,31 @@ public class UnsaturatedFunction1 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction1 other = (UnsaturatedFunction1) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        return true;
+    }
+
 }
index a1ffa2d2ccee5bf6e05206f23f686936a6daadf5..7f02cf51f77f8d2432fb63326c63d3d9b0f541f5 100644 (file)
@@ -65,6 +65,7 @@ public class UnsaturatedFunction2 implements Function {
             nps[i + 2] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -74,4 +75,37 @@ public class UnsaturatedFunction2 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction2 other = (UnsaturatedFunction2) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        return true;
+    }
+
 }
index c9f740c8266f3b35d67dc534ad789eaa2cb76c83..68457f29fd4c135d71b997ee0068e6c792140dc9 100644 (file)
@@ -68,6 +68,7 @@ public class UnsaturatedFunction3 implements Function {
             nps[i + 3] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -78,4 +79,43 @@ public class UnsaturatedFunction3 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction3 other = (UnsaturatedFunction3) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        return true;
+    }
+
 }
index 7d17072ff2d6d5c39315e1c0b5c7be100877b6a3..93baf458601642e25f9297a988069554b1ec4ddd 100644 (file)
@@ -71,6 +71,7 @@ public class UnsaturatedFunction4 implements Function {
             nps[i + 4] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -82,4 +83,49 @@ public class UnsaturatedFunction4 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        result = 31 * result + (p3 == null ? 0 : p3.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction4 other = (UnsaturatedFunction4) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        if(p3 == null) {
+            if (other.p3 != null)
+                return false;
+        } else if (!p3.equals(other.p3))
+            return false;
+        return true;
+    }
+
 }
index bb6e861672a86e32c302d85d8650b0907ed29127..92952170267872e4ba2de48f5b6c3e0956c02975 100644 (file)
@@ -74,6 +74,7 @@ public class UnsaturatedFunction5 implements Function {
             nps[i + 5] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -86,4 +87,55 @@ public class UnsaturatedFunction5 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        result = 31 * result + (p3 == null ? 0 : p3.hashCode());
+        result = 31 * result + (p4 == null ? 0 : p4.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction5 other = (UnsaturatedFunction5) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        if(p3 == null) {
+            if (other.p3 != null)
+                return false;
+        } else if (!p3.equals(other.p3))
+            return false;
+        if(p4 == null) {
+            if (other.p4 != null)
+                return false;
+        } else if (!p4.equals(other.p4))
+            return false;
+        return true;
+    }
+
 }
index cebc2943af9f69ab6c6cbb126e353f715c00e42d..ec20e47e5c4120bd8c103e6b8cb65118435048bf 100644 (file)
@@ -77,6 +77,7 @@ public class UnsaturatedFunction6 implements Function {
             nps[i + 6] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -90,4 +91,61 @@ public class UnsaturatedFunction6 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        result = 31 * result + (p3 == null ? 0 : p3.hashCode());
+        result = 31 * result + (p4 == null ? 0 : p4.hashCode());
+        result = 31 * result + (p5 == null ? 0 : p5.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction6 other = (UnsaturatedFunction6) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        if(p3 == null) {
+            if (other.p3 != null)
+                return false;
+        } else if (!p3.equals(other.p3))
+            return false;
+        if(p4 == null) {
+            if (other.p4 != null)
+                return false;
+        } else if (!p4.equals(other.p4))
+            return false;
+        if(p5 == null) {
+            if (other.p5 != null)
+                return false;
+        } else if (!p5.equals(other.p5))
+            return false;
+        return true;
+    }
+
 }
index c5fdf4a441c28e9b09715cb3238a5b91a1b5d364..0a4f18203db442ae3e6758959cda121605a1f6a3 100644 (file)
@@ -80,6 +80,7 @@ public class UnsaturatedFunction7 implements Function {
             nps[i + 7] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -94,4 +95,67 @@ public class UnsaturatedFunction7 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        result = 31 * result + (p3 == null ? 0 : p3.hashCode());
+        result = 31 * result + (p4 == null ? 0 : p4.hashCode());
+        result = 31 * result + (p5 == null ? 0 : p5.hashCode());
+        result = 31 * result + (p6 == null ? 0 : p6.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction7 other = (UnsaturatedFunction7) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        if(p3 == null) {
+            if (other.p3 != null)
+                return false;
+        } else if (!p3.equals(other.p3))
+            return false;
+        if(p4 == null) {
+            if (other.p4 != null)
+                return false;
+        } else if (!p4.equals(other.p4))
+            return false;
+        if(p5 == null) {
+            if (other.p5 != null)
+                return false;
+        } else if (!p5.equals(other.p5))
+            return false;
+        if(p6 == null) {
+            if (other.p6 != null)
+                return false;
+        } else if (!p6.equals(other.p6))
+            return false;
+        return true;
+    }
+
 }
index 4686cbc2b5e818e0628357cf1555b32c3a811174..6a030e9c0d3183aa8db08f2cacec7c28c907f4bf 100644 (file)
@@ -83,6 +83,7 @@ public class UnsaturatedFunction8 implements Function {
             nps[i + 8] = ps[i];
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -98,4 +99,73 @@ public class UnsaturatedFunction8 implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        int result = f.hashCode();
+        result = 31 * result + (p0 == null ? 0 : p0.hashCode());
+        result = 31 * result + (p1 == null ? 0 : p1.hashCode());
+        result = 31 * result + (p2 == null ? 0 : p2.hashCode());
+        result = 31 * result + (p3 == null ? 0 : p3.hashCode());
+        result = 31 * result + (p4 == null ? 0 : p4.hashCode());
+        result = 31 * result + (p5 == null ? 0 : p5.hashCode());
+        result = 31 * result + (p6 == null ? 0 : p6.hashCode());
+        result = 31 * result + (p7 == null ? 0 : p7.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunction8 other = (UnsaturatedFunction8) obj;
+        if(!f.equals(other.f))
+            return false;
+        if(p0 == null) {
+            if (other.p0 != null)
+                return false;
+        } else if (!p0.equals(other.p0))
+            return false;
+        if(p1 == null) {
+            if (other.p1 != null)
+                return false;
+        } else if (!p1.equals(other.p1))
+            return false;
+        if(p2 == null) {
+            if (other.p2 != null)
+                return false;
+        } else if (!p2.equals(other.p2))
+            return false;
+        if(p3 == null) {
+            if (other.p3 != null)
+                return false;
+        } else if (!p3.equals(other.p3))
+            return false;
+        if(p4 == null) {
+            if (other.p4 != null)
+                return false;
+        } else if (!p4.equals(other.p4))
+            return false;
+        if(p5 == null) {
+            if (other.p5 != null)
+                return false;
+        } else if (!p5.equals(other.p5))
+            return false;
+        if(p6 == null) {
+            if (other.p6 != null)
+                return false;
+        } else if (!p6.equals(other.p6))
+            return false;
+        if(p7 == null) {
+            if (other.p7 != null)
+                return false;
+        } else if (!p7.equals(other.p7))
+            return false;
+        return true;
+    }
+
 }
index c53b34735e4f1fdf4896227beb1b434148306f65..2ed78c5c4be38672dfd260dab473384f2668ff6f 100644 (file)
@@ -4,6 +4,8 @@
  */
 package org.simantics.scl.runtime.function;
 
+import java.util.Arrays;
+
 @SuppressWarnings("all")
 public class UnsaturatedFunctionN implements Function {
     private final Function f;
@@ -113,6 +115,7 @@ public class UnsaturatedFunctionN implements Function {
         System.arraycopy(ops, 0, nps, ps.length, ops.length);
         return f.applyArray(nps);
     }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -122,4 +125,22 @@ public class UnsaturatedFunctionN implements Function {
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public int hashCode() {
+        return f.hashCode() + 31 * Arrays.hashCode(ps);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UnsaturatedFunctionN other = (UnsaturatedFunctionN) obj;
+        return f.equals(other.f) && Arrays.equals(ps, other.ps);
+    }
+
 }
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/reporting/SCLReportingWriter.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/reporting/SCLReportingWriter.java
new file mode 100644 (file)
index 0000000..424eeaa
--- /dev/null
@@ -0,0 +1,44 @@
+package org.simantics.scl.runtime.reporting;
+
+import java.io.Writer;
+
+public class SCLReportingWriter extends Writer {
+       
+       StringBuilder builder = null;
+       
+       public SCLReportingWriter() {
+               builder = new StringBuilder();
+       }
+       
+       @Override
+       public void close() {
+               flush();
+       }
+
+       @Override
+       public void flush() {
+               if (builder.length() > 0) {
+                       SCLReporting.print(builder.toString());
+                       builder.setLength(0);
+               }
+       }
+
+       @Override
+       public void write(char[] buf, int off, int len) {
+               if (len == 0) return;
+               
+               if (len < 0) throw new IllegalArgumentException("Negative buffer region length");
+               if (off < 0) throw new IllegalArgumentException("Negative buffer region offset");
+               if (off + len > buf.length) throw new IllegalArgumentException("Buffer region overflow");
+               
+               for (int i = 0; i < len; i++) {
+                       if (buf[off + i] == '\n') {
+                               SCLReporting.print(builder.toString());
+                               builder.setLength(0);
+                       }
+                       else {
+                               builder.append(buf[off + i]);
+                       }
+               }
+       }
+}
index 9006f3cc2bd12d4d2d3dc98d654940dd209533cb..de335f0f944c3ba7135b5ba6900398f6cd91b4c5 100644 (file)
@@ -18,7 +18,9 @@ import org.simantics.scl.compiler.errors.Failable;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
 import org.simantics.scl.compiler.module.ImportDeclaration;
+import org.simantics.scl.compiler.module.InvalidModulePathException;
 import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.module.ModuleUtils;
 import org.simantics.scl.compiler.module.repository.ImportFailureException;
 import org.simantics.scl.compiler.types.TCon;
 import org.simantics.scl.osgi.SCLOsgi;
@@ -103,44 +105,18 @@ public class SCLTextEditorEnvironment {
     private ArrayList<ImportDeclaration> processRelativeImports(List<ImportDeclaration> relativeImports) {
         ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
         for(ImportDeclaration relativeImport : relativeImports) {
-            if(relativeImport.moduleName.startsWith(".")) {
-                String absoluteModuleName = convertRelativeModulePath(relativeImport.moduleName);
-                if(absoluteModuleName != null)
-                    absoluteImports.add(new ImportDeclaration(
-                            absoluteModuleName, relativeImport.localName,
-                            relativeImport.reexport, relativeImport.spec));
-            }
-            else
-                absoluteImports.add(relativeImport);
+                       try {
+                               String absoluteModuleName = ModuleUtils.resolveAbsolutePath(moduleName, relativeImport.moduleName);
+                absoluteImports.add(new ImportDeclaration(
+                        absoluteModuleName, relativeImport.localName,
+                        relativeImport.reexport, relativeImport.spec));
+                       } catch (InvalidModulePathException e) {
+               // Nothing to do
+                       }
         }
         return absoluteImports;
     }
 
-    private String convertRelativeModulePath(String relativeModuleName) {
-        String originalRelativeModuleName = relativeModuleName;
-        int p = moduleName.lastIndexOf('/');
-        String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
-        while(relativeModuleName.startsWith(".")) {
-            if(relativeModuleName.startsWith("./")) {
-                relativeModuleName = relativeModuleName.substring(2);
-            }
-            else if(relativeModuleName.startsWith("../")) {
-                relativeModuleName = relativeModuleName.substring(3);
-                if(parentPackage.isEmpty()) {
-                    System.err.println("Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
-                    return null;
-                }
-                p = parentPackage.lastIndexOf('/');
-                parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
-            }
-            else {
-                System.err.println("Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
-                return null;
-            }
-        }
-        return parentPackage + "/" + relativeModuleName;
-    }
-
     private static final Comparator<SCLCompletionProposal> COMPARATOR = new Comparator<SCLCompletionProposal>() {
 
         @Override
index cd59c874d61c93ab6c27825170882a34a249d704..4b6818ab7b805587bfe6306a9f1154e48ac0e3ad 100644 (file)
@@ -9,6 +9,10 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.PlatformUI;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.module.InvalidModulePathException;
+import org.simantics.scl.compiler.module.ModuleUtils;
+import org.simantics.scl.compiler.source.ModuleSource;
+import org.simantics.scl.osgi.SCLOsgi;
 import org.simantics.scl.ui.editor.completion.SCLTextEditorEnvironment;
 
 public class OpenDeclaration extends AbstractHandler {
@@ -83,8 +87,16 @@ public class OpenDeclaration extends AbstractHandler {
         if(lineAtCaret.startsWith("import ") || lineAtCaret.startsWith("include ")) {
             int p1 = lineAtCaret.indexOf('"', 6);
             int p2 = lineAtCaret.indexOf('"', p1+1);
-            String moduleName = lineAtCaret.substring(p1+1, p2);
-            OpenSCLModule.openModule(moduleName);
+            SCLModuleEditorInput input = (SCLModuleEditorInput)moduleEditor.getEditorInput();
+            try {
+                   String moduleName = ModuleUtils.resolveAbsolutePath(input.getModuleName(), lineAtCaret.substring(p1+1, p2));
+               ModuleSource source = SCLOsgi.SOURCE_REPOSITORY.getModuleSource(moduleName, null);
+                if (source != null) {
+                       OpenSCLModule.openModule(moduleName);
+                }
+            } catch (InvalidModulePathException e) {
+               // Nothing to do
+            }
         }
         else {
             // Try to find an identifier at caret
index 724deb153af635e054d7f73ad28e8991e96f162b..cb9e2f834845321935d9706b22b26e8108c3ec59 100644 (file)
Binary files a/bundles/org.simantics.selectionview.ontology/graph.tg and b/bundles/org.simantics.selectionview.ontology/graph.tg differ
index 58eba84710132a5ab488f22f38be866ada848eef..cc1bc6200966b072421cffb47631929cfb636c01 100644 (file)
@@ -132,7 +132,7 @@ SEL.CategoryHidden : SEL.StandardPropertyInfo
   SEL.StandardPropertyInfo.CategorySortingName ""
   SEL.StandardPropertyInfo.IsHidden true
 
-SEL.getSpecialCategory ==> "Resource -> <ReadGraph> Resource" <R L0.HasProperty : L0.FunctionalRelation
+SEL.getSpecialCategory ==> "Resource -> <ReadGraph> Maybe Resource" <R L0.HasProperty : L0.FunctionalRelation
 
 SEL.ColorParameterType <T SEL.GenericParameterType
   @L0.assert SEL.HasDisplayValue
index a0f65152b08e65a3f0c9dc9bf89a485673d0f9a6..5b19d1986a7d3a12f16d25ee3d05102b5a0cd867 100644 (file)
Binary files a/bundles/org.simantics.selectionview.ui.ontology/graph.tg and b/bundles/org.simantics.selectionview.ui.ontology/graph.tg differ
index 0fb82a9aff0c9dccd806b234e201a957dcd3ef81..704e7430c417a7541255b2cd8d3e6f3242c9f02e 100644 (file)
@@ -10,6 +10,10 @@ SEL = <http://www.simantics.org/SelectionViewUI-1.1> : L0.Ontology
     @L0.new
     L0.HasResourceClass "org.simantics.selectionview.ui.ontology.SelectionViewUIResources"
 
+SEL.SCLMain : L0.SCLModule
+    L0.SCLModule.definition _ : L0.String
+      @L0.loadString "scl/SCLMain.scl"
+
 SEL.CategoryNode : VP.NodeType
   VP.HasContentType "org.simantics.selectionview.CategoryNode"
   VP.HasBundle "org.simantics.selectionview"
@@ -83,11 +87,17 @@ SEL.StandardProperties.BrowseContextStandardChildren <T SEL.StandardProperties.B
       VP.ChildContribution.HasChildNodeType SEL.CategoryNode
       VP.ChildContribution.HasRule 
         SEL.StandardProperties.BrowseContextStandardChildren.Cat : SEL.VariablePropertyCategoryRule
+          @MOD.scl SEL_BASE.getSpecialCategory "layer0Categories" "Resource -> <ReadGraph> Maybe Resource"
   @L0.assert VP.BrowseContext.HasVisualsContribution
     _ : VP.VisualsContribution
       VP.VisualsContribution.HasNodeType MOD.ModelingBrowseContext.Variable
       VP.VisualsContribution.HasRule
         SEL.StandardProperties.BrowseContextStandardChildren.Sorter : SEL.StandardPropertySorterRuleType
+          @MOD.scl SEL_BASE.getSpecialCategory "layer0Categories" "Resource -> <ReadGraph> Maybe Resource"
+  @L0.assert  VP.BrowseContext.HasVisualsContribution
+    _ : VP.VisualsContribution
+      VP.VisualsContribution.HasNodeType MOD.ModelingBrowseContext.Variable
+      VP.VisualsContribution.HasRule VP.DescriptionTooltipRule
 
 SEL.StandardProperties.BrowseContextWithoutChildren <T VP.BrowseContext
   @L0.assert VP.BrowseContext.HasVisualsContribution
diff --git a/bundles/org.simantics.selectionview.ui.ontology/graph/scl/SCLMain.scl b/bundles/org.simantics.selectionview.ui.ontology/graph/scl/SCLMain.scl
new file mode 100644 (file)
index 0000000..2184c61
--- /dev/null
@@ -0,0 +1,7 @@
+include "Simantics/All"
+
+layer0Categories :: Resource -> <ReadGraph> Maybe Resource
+layer0Categories predicate = match predicate with
+  L0.HasName -> Just MOD.SystemPropertyInfo
+  _ -> Nothing
+  
\ No newline at end of file
index cdf0fa26fec940ee1d71406f381f8dafc8ea9512..b3b474592924db6526f71d61d4ecbdca4092f763 100644 (file)
@@ -14,6 +14,7 @@ public class SelectionViewUIResources {
     public final Resource CategoryNode;
     public final Resource CategoryNodeLabelRule;
     public final Resource PropertyColumn;
+    public final Resource SCLMain;
     public final Resource StandardProperties;
     public final Resource StandardPropertiesBase;
     public final Resource StandardPropertiesBase_BrowseContext;
@@ -37,6 +38,7 @@ public class SelectionViewUIResources {
         public static final String CategoryNode = "http://www.simantics.org/SelectionViewUI-1.1/CategoryNode";
         public static final String CategoryNodeLabelRule = "http://www.simantics.org/SelectionViewUI-1.1/CategoryNodeLabelRule";
         public static final String PropertyColumn = "http://www.simantics.org/SelectionViewUI-1.1/PropertyColumn";
+        public static final String SCLMain = "http://www.simantics.org/SelectionViewUI-1.1/SCLMain";
         public static final String StandardProperties = "http://www.simantics.org/SelectionViewUI-1.1/StandardProperties";
         public static final String StandardPropertiesBase = "http://www.simantics.org/SelectionViewUI-1.1/StandardPropertiesBase";
         public static final String StandardPropertiesBase_BrowseContext = "http://www.simantics.org/SelectionViewUI-1.1/StandardPropertiesBase/BrowseContext";
@@ -70,6 +72,7 @@ public class SelectionViewUIResources {
         CategoryNode = getResourceOrNull(graph, URIs.CategoryNode);
         CategoryNodeLabelRule = getResourceOrNull(graph, URIs.CategoryNodeLabelRule);
         PropertyColumn = getResourceOrNull(graph, URIs.PropertyColumn);
+        SCLMain = getResourceOrNull(graph, URIs.SCLMain);
         StandardProperties = getResourceOrNull(graph, URIs.StandardProperties);
         StandardPropertiesBase = getResourceOrNull(graph, URIs.StandardPropertiesBase);
         StandardPropertiesBase_BrowseContext = getResourceOrNull(graph, URIs.StandardPropertiesBase_BrowseContext);
index 53d5638b242daabe6e2f682d3514091163a1a2cd..f1ba40ed48468bdc5d834b193578a12c894beede 100644 (file)
@@ -12,7 +12,8 @@ Require-Bundle: org.simantics.ui;bundle-version="1.0.0",
  org.simantics.modeling.ontology;bundle-version="1.2.0",
  org.simantics.fastlz;bundle-version="1.2.1",
  org.apache.commons.compress;bundle-version="1.7.0",
- org.simantics.lz4;bundle-version="1.3.0"
+ org.simantics.lz4;bundle-version="1.3.0",
+ org.slf4j.api;bundle-version="1.7.0"
 Export-Package: org.simantics.simulation,
  org.simantics.simulation.data,
  org.simantics.simulation.experiment,
index b4222df012e4a56d8533914fa0c751adfd724fef..41125d0a0ad2f086cb90201c05f15c432d8bebcc 100644 (file)
@@ -19,6 +19,8 @@ import org.simantics.databoard.accessor.Accessor;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.Listener;
+import org.simantics.db.request.ExternalRead;
 import org.simantics.utils.datastructures.ListenerList;
 
 public abstract class Experiment implements IExperiment {
@@ -64,7 +66,7 @@ public abstract class Experiment implements IExperiment {
     
     @Override
     public ExperimentState getState(ReadGraph graph) throws DatabaseException {
-       throw new UnsupportedOperationException();
+       return graph.syncRequest(EXPERIMENT_STATE_READ);
     }
 
     public void changeState(ExperimentState newState) {
@@ -136,4 +138,37 @@ public abstract class Experiment implements IExperiment {
         return identifier;
     }
 
+    static class ExperimentStateRead implements ExternalRead<ExperimentState>, Runnable {
+       
+       final private Experiment experiment;
+        private Listener<ExperimentState> listener = null;
+        
+        ExperimentStateRead(Experiment experiment) {
+               this.experiment = experiment;
+        }
+
+        @Override
+        public void register(ReadGraph graph, final Listener<ExperimentState> procedure) {
+            //System.out.println("IcTrackerRequest.register: " + procedure);
+            listener = procedure;
+            procedure.execute(experiment.state);
+        }
+
+        @Override
+        public void unregistered() {
+            //System.out.println("IcTrackerRequest.unregister: " + listener);
+            listener = null;
+        }
+
+        @Override
+        public void run() {
+            Listener<ExperimentState> l = listener;
+            //System.out.println("IcTrackerRequest.run: " + l);
+            if (l != null)
+                l.execute(experiment.state);
+        }
+    }
+
+    private ExperimentStateRead EXPERIMENT_STATE_READ = new ExperimentStateRead(this);
+    
 }
index 24f6065c5117a6e6660d336edfeefa3c56f43593..a819ef8ed915462da196d5e120ceee3a6a070021 100644 (file)
@@ -47,6 +47,10 @@ public final class ExperimentUtil {
             ((IDynamicExperiment)experiment).simulate(enabled);
     }
 
+    public static ExperimentState getExperimentState(ReadGraph graph, IExperiment experiment) throws DatabaseException {
+       return experiment.getState(graph);
+    }
+        
     public static void disposeExperiment(final IExperiment experiment) {
        
         if(experiment instanceof IDynamicExperiment) {
index ec56854751f55bc5d5666cb29422b6a7ff10e184..613346b1147830521336c31d7a64c761e0f6da60 100644 (file)
@@ -37,12 +37,16 @@ import org.simantics.simulation.experiment.IExperimentListener;
 import org.simantics.simulation.model.IModel;
 import org.simantics.ui.workbench.WorkbenchShutdownService;
 import org.simantics.utils.datastructures.ListenerList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Simple local ExperimentManager implementation
  */
 public class ExperimentManager implements IExperimentManager {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentManager.class);
+
     CopyOnWriteArrayList<IExperimentManagerListener> listeners = new CopyOnWriteArrayList<IExperimentManagerListener>();
     ListenerList<IExperiment> experiments = new ListenerList<IExperiment>(IExperiment.class);
     IExperiment activeExperiment;
@@ -218,9 +222,9 @@ public class ExperimentManager implements IExperimentManager {
 
             if (!listeners.isEmpty()) {
                 // Some clients are leaking listeners. Shame on them.
-                System.err.println("ExperimentManager still contains the following listeners after disposal:");
+                LOGGER.warn("ExperimentManager still contains the following listeners after disposal:");
                 for (IExperimentManagerListener listener : listeners)
-                    System.err.println("\t" + listener);
+                    LOGGER.warn("\t" + listener);
             }
         }
     }
index 2face448f40973faf7135e6575e99776ead55a4e..fb80d07605493f42119f05af20f38d5d8ae766fa 100644 (file)
  *******************************************************************************/
 package org.simantics.spreadsheet.common;
 
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontData;
+import org.simantics.document.server.io.IFont;
 import org.simantics.document.server.io.ITreeTableCell;
+import org.simantics.document.server.io.SimpleFont;
 
 public class TreeTableCell extends TableCell implements ITreeTableCell {       
        
        private int parent = -1;
+       
+       private boolean editable = true;
+       private Object data;
 
        public TreeTableCell() {
        }
        
+       public TreeTableCell(String text, Object data, Object font, int parent, int row, int column, boolean editable) {
+               super(column, row, 0, 0, text, (IFont)font, null, null, false, 1, 1);
+               this.editable = editable;
+               this.parent = parent;
+               this.data = data;
+       }
+       
+       public static TreeTableCell createTreeTableCell(String text, Object data, Object font, int parent, int row, int column, boolean editable) {
+               return new TreeTableCell(text, data, extractIFont(font), parent, row, column, editable);
+       }
+       
+       private static IFont extractIFont(Object font) {
+               if(font instanceof FontDescriptor) {
+                       FontDescriptor descriptor = (FontDescriptor)font;
+                       String family = "";
+                       String style = "";
+                       int size = 12;
+                       for(FontData d : descriptor.getFontData()) {
+                               System.err.println("data: " + d);
+                               family = d.getName();
+                               if((d.getStyle() & SWT.ITALIC) != 0) style += "Italic";
+                               if((d.getStyle() & SWT.BOLD) != 0) style += "Bold";
+                               size = d.getHeight();
+                       }
+                       return new SimpleFont(family, style, size);
+               }
+               return null;
+       }
+       
        public void setParent(int parent) {
                this.parent = parent;
        }
@@ -30,4 +67,14 @@ public class TreeTableCell extends TableCell implements ITreeTableCell {
                return parent;
        }
 
+       @Override
+       public Object getData() {
+               return data;
+       }
+
+       @Override
+       public boolean isEditable() {
+               return editable;
+       }
+
 }
index 3963f6e7b1b6d0857b8d58d8e68fd67c682d4c47..6719f5913fd6c288a741b6c0359d69d0eb47444b 100644 (file)
@@ -18,8 +18,8 @@ public class ExcelFileImport extends SimanticsResourceFileImport {
     }
     
     @Override
-    public Optional<Resource> perform(Resource parent, Path file) {
-        return Optional.empty();
+    public Optional<Resource> perform(Resource parent, Path file) throws Exception {
+        throw new UnsupportedOperationException("Excel import is not yet supported");
     }
 
     @Override
index ddfd3bef027adc184773dc43efe6cac5316c94ad..532331e55eec36fab7f7c36a3fbb4cc643eb354d 100644 (file)
@@ -10,6 +10,20 @@ importJava "org.simantics.spreadsheet.common.TableCell" where
 importJava "org.simantics.spreadsheet.common.TreeTableCell" where
     data TreeTableCell
 
+    @JavaName getData
+    getTreeTableCellData :: TreeTableCell -> <Proc> a
+    
+    createTreeTableCell :: String -> a -> Maybe b -> Integer -> Integer -> Integer -> Boolean -> <Proc> TreeTableCell
+    
+    @JavaName getText
+    treeTableCellText :: TreeTableCell -> <Proc> String
+    @JavaName getFont
+    treeTableCellFont :: TreeTableCell -> <Proc> Maybe IFont
+    @JavaName getRow
+    treeTableCellRow :: TreeTableCell -> <Proc> Integer
+    @JavaName getColumn
+    treeTableCellColumn :: TreeTableCell -> <Proc> Integer
+    
 importJava "org.simantics.spreadsheet.common.SpreadsheetCell" where
     data SpreadsheetCell
 
index 8ad7b0843382d31d31c47d0c02f35187d03d19d3..405ddb99487194ee81f9bd280e5e142110336bd9 100644 (file)
Binary files a/bundles/org.simantics.spreadsheet.ontology/graph.tg and b/bundles/org.simantics.spreadsheet.ontology/graph.tg differ
index 027c88dc722d5232bd5229b29491e85b2bc355a5..1615aaf2ba35e8e4cd66c1cd009897e2005988fc 100644 (file)
@@ -80,7 +80,11 @@ public class ModuleUpdateContext<T extends ComponentBase<T>> {
     public <S> S getConcreteSolver() {
        return handler.solver.getConcreteSolver();
     }
-    
+
+    public String getModuleType() {
+        return updater != null ? updater.moduleType : null;
+    }
+
     public String getModuleName() {
         return component.solverComponentName;
     }
index 55128b89e29fba7fd3461c401c7376d89115b8b7..4112d905134e5b9319a86e8db55a1f14a7112f6c 100644 (file)
@@ -28,7 +28,7 @@ import org.eclipse.swt.widgets.MenuItem;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.ui.utils.ResourceAdaptionUtils;
+import org.simantics.ui.selection.WorkbenchSelectionUtils;
 import org.simantics.ui.workbench.action.ResourceEditorAdapterAction;
 import org.simantics.ui.workbench.editor.EditorAdapter;
 import org.simantics.ui.workbench.editor.EditorRegistry;
@@ -58,7 +58,8 @@ public class OpenWithMenuContribution extends DynamicMenuContribution {
     }
 
     protected Object extractResource(ReadGraph graph, Object object) throws DatabaseException {
-       Resource resource = ResourceAdaptionUtils.adaptToResource(graph, object);
+       Resource resource = WorkbenchSelectionUtils.getPossibleResource(object);
+       //Resource resource = ResourceAdaptionUtils.adaptToResource(graph, object);
        if(resource != null) return resource;
        else return object; 
     }
index b194694b58e01a3868861dd0e82bd6847a6e533b..a49073a4d7a7ddbe0ffd07e7340f8f34edd88bb7 100644 (file)
@@ -28,6 +28,7 @@ import org.simantics.layer0.utils.operations.IOperation;
 import org.simantics.project.IProject;
 import org.simantics.ui.SimanticsUI;
 import org.simantics.ui.icons.ImageUtil;
+import org.simantics.ui.selection.WorkbenchSelectionUtils;
 import org.simantics.ui.utils.ResourceAdaptionUtils;
 import org.simantics.utils.datastructures.persistent.ContextMap;
 
@@ -48,9 +49,9 @@ public abstract class OperationsMenuContribution extends DynamicMenuContribution
     }
 
     @Override
-    protected IAction[] getActions(ReadGraph g, Object[] selection) {
+    protected IAction[] getActions(ReadGraph g, Object[] selection) throws DatabaseException {
         if(selection.length == 1) {
-            final Resource r = ResourceAdaptionUtils.adaptToResource(selection[0]);
+            final Resource r = WorkbenchSelectionUtils.getPossibleResource(selection[0]);
             if(r == null)
                return NO_ACTIONS;
             try {
index 34b01b8f21a09a3e71ff3999b9bba102f7bf12fe..765a37c2a8e60c8c4f009bf513a659044a4a8863 100644 (file)
@@ -119,8 +119,8 @@ public class WorkbenchSelectionUtils {
        }
 
        public static Resource getPossibleResource(RequestProcessor processor, Object input, Resource type) throws DatabaseException {
-           if(input instanceof Collection && !((Collection)input).isEmpty()) {
-               Object element = ((Collection)input).iterator().next();
+           if(input instanceof Collection && !((Collection<?>)input).isEmpty()) {
+               Object element = ((Collection<?>)input).iterator().next();
                if(element instanceof Resource)
                    return (Resource)element;
            }
index b952966e493509ad5e11e6b8897b29273c52deaa..9fdfbb4ddd2463dc0763a365e65a3ecd6079a638 100644 (file)
@@ -17,6 +17,7 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -105,7 +106,8 @@ public final class EditorRegistry implements IExtensionChangeHandler, IEditorReg
 
     private static final String ATTR_ID              = "id";
 
-
+    private static final Comparator<EditorAdapter> ADAPTER_COMPARATOR = (o1, o2) -> -(o1.getPriority() - o2.getPriority());
+    
     private static class Group {
         public final String id;
         public final List<EditorAdapterDescriptor> adapters;
@@ -558,6 +560,9 @@ public final class EditorRegistry implements IExtensionChangeHandler, IEditorReg
         }
         
         result = gatherAdapterResult(l);
+        
+        Arrays.sort(result, ADAPTER_COMPARATOR);
+        
         updateCache(r, result);
 
         if (status != null && !status.isOK())
index e384efeb981a1bfd4e3b89f787eefcc99c74b991..331a81cd0d02905c332c46832885717ceeeda89b 100644 (file)
  *******************************************************************************/
 package org.simantics.utils.datastructures;
 
-public interface BinaryCallback<T1, T2> {
+import java.util.function.BiConsumer;
+
+/**
+ * @deprecated use {@link BiConsumer} instead
+ */
+@Deprecated
+public interface BinaryCallback<T1, T2> extends BiConsumer<T1, T2> {
 
     void run(T1 arg1, T2 arg2);
-    
+
+    @Override
+    default void accept(T1 arg, T2 arg2) {
+        run(arg, arg2);
+    }
+
 }
index 6bf58494bbf673cf8f66a16e73735e16c97ac5d2..5ba3face27335128c7014737be237c0fb5f3a97e 100644 (file)
@@ -18,8 +18,13 @@ import java.util.function.Supplier;
  */
 @Deprecated
 @FunctionalInterface
-public interface Callable<T> {
+public interface Callable<T> extends Supplier<T> {
 
     public T call();
 
+    @Override
+    default T get() {
+        return call();
+    }
+
 }
index 42eed9b89040873ef7d26a4cbe9e0cc3045420d7..99e952bb4d7de707524981b6c4a122fdee8bd20d 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.utils.datastructures;
 
 import java.io.PrintStream;
 import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
 
 
 /**
@@ -31,7 +32,7 @@ public final class TimingUtil {
         }
     }
 
-    public static class PrintCallback implements BinaryCallback<Long, TimeUnit> {
+    public static class PrintCallback implements BiConsumer<Long, TimeUnit> {
         String task;
         PrintStream stream;
         PrintCallback(String task) {
@@ -42,7 +43,7 @@ public final class TimingUtil {
             this.stream = stream;
         }
         @Override
-        public void run(Long arg1, TimeUnit arg2) {
+        public void accept(Long arg1, TimeUnit arg2) {
             stream.println(task + " took " + arg1 + " " + arg2.toString());
         }
     };
@@ -59,11 +60,11 @@ public final class TimingUtil {
         time(runnable, reportTimeUnit, new PrintCallback(runnable.toString(), stream));
     }
 
-    public static void time(Runnable runnable, TimeUnit reportTimeUnit, BinaryCallback<Long, TimeUnit> result) {
+    public static void time(Runnable runnable, TimeUnit reportTimeUnit, BiConsumer<Long, TimeUnit> result) {
         long start = System.nanoTime();
         runnable.run();
         long end = System.nanoTime();
-        result.run(reportTimeUnit.convert(end-start, TimeUnit.NANOSECONDS), reportTimeUnit);
+        result.accept(reportTimeUnit.convert(end-start, TimeUnit.NANOSECONDS), reportTimeUnit);
     }
 
 }
index bb38164b79dfb0d2f9dbe5f43d99185d3ba6ac14..bb2148f4803d4923c7a70ad15bb778924f21ca13 100644 (file)
  *******************************************************************************/
 package org.simantics.utils.datastructures;
 
-public interface UnaryFunction<R, A> {
+import java.util.function.Function;
+
+/**
+ * @deprecated use {@link Function} instead
+ */
+@Deprecated
+public interface UnaryFunction<R, A> extends Function<A, R> {
 
     public R call(A arg);
-    
+
+    @Override
+    default R apply(A t) {
+        return call(t);
+    }
+
 }
index b5bb6722c43e8531dc42c80f32ac5043846752da..07102a102cd8b861210a31d9ec26de60478b8c6c 100644 (file)
@@ -22,25 +22,32 @@ import org.eclipse.swt.widgets.Widget;
 
 public class SWTThread implements IThreadWorkQueue, Executor {
 
-       final Display display;
+       private final Display display;
+       private final boolean executeAsync;
+       
+       public static IThreadWorkQueue getThreadAccess(Display display, boolean executeAsync)
+       {
+               return new SWTThread(display, executeAsync);
+       }
        
        public static IThreadWorkQueue getThreadAccess(Display display)
        {
-               return new SWTThread(display);
+               return getThreadAccess(display, false);
        }
        
        public static IThreadWorkQueue getThreadAccess(Widget widget)
        {
-               return new SWTThread(widget.getDisplay());
+               return new SWTThread(widget.getDisplay(), false);
        }
        
        public static IThreadWorkQueue getThreadAccess() {
-               return new SWTThread(Display.getDefault());
+               return new SWTThread(Display.getDefault(), false);
        }
        
-       SWTThread(Display display)
+       SWTThread(Display display, boolean executeAsync)
        {
                this.display = display;
+               this.executeAsync = executeAsync;
        }
        
        @Override
@@ -87,6 +94,7 @@ public class SWTThread implements IThreadWorkQueue, Executor {
 
        @Override
        public void execute(Runnable command) {
-               syncExec(command);
+               if (executeAsync) asyncExec(command);
+               else syncExec(command);
        }
 }
index c71e2515697d70c6b8c7b93ea604129679204e11..44435fa6ed41421f640db3fa1312de4e0857c81d 100644 (file)
@@ -6,5 +6,4 @@ Bundle-Version: 1.1.0.qualifier
 Export-Package: org.simantics.utils.threads,
  org.simantics.utils.threads.logger
 Bundle-Vendor: VTT Technical Research Centre of Finland
-Require-Bundle: org.eclipse.swt;bundle-version="3.6.0";resolution:=optional
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/bundles/org.simantics.utils.thread/src/org/simantics/utils/threads/Executors2.java b/bundles/org.simantics.utils.thread/src/org/simantics/utils/threads/Executors2.java
deleted file mode 100644 (file)
index 66af979..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
- * 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.utils.threads;
-
-import java.util.concurrent.Executor;
-
-import org.eclipse.swt.widgets.Display;
-
-public class Executors2 {
-
-       public static Executor createSWTExecutor(Display display, boolean async) {
-               return async ? new SWTExecutorAsync(display) : new SWTExecutorSync(display);
-       }
-       
-}
-
-class SWTExecutorAsync implements Executor {
-       
-       Display display;
-       public SWTExecutorAsync(Display display)
-       {
-               this.display = display;
-       }
-       
-       @Override
-       public void execute(Runnable command) {
-               // Don't accept work if the SWT thread is disposed.
-               if (display.isDisposed()) 
-                       throw new RuntimeException("The SWT thread has been disposed"); 
-               display.asyncExec(command);
-       }
-       
-}
-
-class SWTExecutorSync implements Executor {
-       
-       Display display;
-       public SWTExecutorSync(Display display)
-       {
-               this.display = display;
-       }
-       
-       @Override
-       public void execute(Runnable command) {
-               // Don't accept work if the SWT thread is disposed.
-               if (display.isDisposed()) 
-                       throw new RuntimeException("The SWT thread has been disposed"); 
-               display.syncExec(command);
-       }
-       
-}
-
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/dialogs/InfoDialog.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/dialogs/InfoDialog.java
new file mode 100644 (file)
index 0000000..53a0957
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.utils.ui.dialogs;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IconAndMessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class InfoDialog extends IconAndMessageDialog {
+
+       private String title;
+       private Text messageText;
+
+       protected InfoDialog(Shell parentShell, String title, String message) {
+               super(parentShell);
+               this.title = title;
+               this.message = message;
+               setShellStyle(getShellStyle() | SWT.RESIZE);
+       }
+
+       @Override
+       protected Image getImage() {
+               return getInfoImage();
+       }
+
+       @Override
+       protected void configureShell(Shell newShell) {
+               super.configureShell(newShell);
+               newShell.setText(title);
+               newShell.setImage(newShell.getDisplay().getSystemImage(SWT.ICON_INFORMATION));
+       }
+
+       protected Control createMessageArea(Composite composite) {
+               // create image
+               Image image = getImage();
+               if (image != null) {
+                       imageLabel = new Label(composite, SWT.NULL);
+                       image.setBackground(imageLabel.getBackground());
+                       imageLabel.setImage(image);
+                       GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING)
+                       .applyTo(imageLabel);
+               }
+               // create message
+               if (message != null) {
+                       messageText = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.FLAT | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL);
+                       messageText.setEditable(false);
+                       messageText.setText(message);
+                       GridDataFactory
+                       .fillDefaults()
+                       .grab(true, true)
+                       .hint(
+                                       convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH),
+                                       SWT.DEFAULT).applyTo(messageText);
+               }
+               return composite;
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite composite = new Composite(parent, SWT.NONE);
+
+               createMessageArea(composite);
+
+               GridLayout layout = new GridLayout();
+               layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+               layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+               layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+               layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+               layout.numColumns = 2;
+               composite.setLayout(layout);
+               GridData childData = new GridData(GridData.FILL_BOTH);
+               childData.horizontalSpan = 2;
+               childData.grabExcessVerticalSpace = true;
+               composite.setLayoutData(childData);
+               applyDialogFont(composite);
+
+               return composite;
+       }
+
+       protected void createButtonsForButtonBar(Composite parent) {
+               // create OK button by default
+               createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+                               true);
+       }
+
+       @Override
+       protected void buttonPressed(int buttonId) {
+               super.buttonPressed(buttonId);
+       }
+
+       public static boolean open(Shell parent, String title, String message, int style) {
+               InfoDialog dialog = new InfoDialog(parent, title, message);
+               style &= SWT.SHEET;
+               dialog.setShellStyle(dialog.getShellStyle() | style);
+               return dialog.open() == 0;
+       }
+
+}
\ No newline at end of file
index c500c66350b937e6d5d6d61ff6e9d7800ffc4115..ab3d249d3bd95e157dcdb6af12caa87dba737353 100644 (file)
@@ -22,6 +22,31 @@ public interface FileService {
                }
        }
 
+       @FunctionalInterface
+       public static interface FileOperation {
+               IOperation<Boolean, IOException> perform(File file);
+
+               default void perform(File... files) {
+                       for (File f : files)
+                               perform(f);
+               }
+       }
+
+       public static class DeleteOperation implements FileOperation {
+               private final FileService service;
+               private final DeleteOption[] options;
+
+               public DeleteOperation(FileService service, DeleteOption... options) {
+                       this.service = service;
+                       this.options = options;
+               }
+
+               @Override
+               public IOperation<Boolean, IOException> perform(File file) {
+                       return service.scheduleDeleteIfExists(file, options);
+               }
+       }
+
        /**
         * Schedules a file to be deleted at some point in the future when the
         * system allows it to be deleted if ever.
@@ -33,4 +58,16 @@ public interface FileService {
         */
        IOperation<Boolean, IOException> scheduleDeleteIfExists(File file, DeleteOption... options);
 
+       /**
+        * @param options
+        *            the deletion options to be used by the returned FileOperation
+        * @return a FileOperation that runs
+        *         {@link #scheduleDeleteIfExists(File, DeleteOption...)} for any
+        *         files given to it
+        * @since 1.28.0
+        */
+       default FileOperation deleteOperation(DeleteOption... options) {
+               return new DeleteOperation(this, options);
+       }
+
 }
index b794c9360473a360d973ba5826a3d96eef942a62..4e68f29c4ac95246da7d81d2b9e14c7b323dafbc 100644 (file)
@@ -492,7 +492,7 @@ public class FileUtils {
                 }              
             }
         } else if (dir.exists()) {
-               if (filter.contains(dir.getAbsolutePath())) {
+               if (!filter.contains(dir.getAbsolutePath())) {
                 if (!dir.delete()) {
                     throw new IOException("Could not delete file: " + dir.getAbsolutePath());
                 }
@@ -1013,4 +1013,10 @@ public class FileUtils {
             return FileVisitResult.CONTINUE;
         }
     }
+    
+    public static void syncFile(File file) throws IOException {
+       try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
+               raf.getFD().sync();
+               }
+    }
 }
index d3163ee7b1ffe3c367ff1a474087a2733915c45d..12a8c0b7df31ff5c4344b4e46f5622062feb2ede 100644 (file)
Binary files a/bundles/org.simantics.viewpoint.ontology/graph.tg and b/bundles/org.simantics.viewpoint.ontology/graph.tg differ
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ButtonLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ButtonLoader.java.keep
deleted file mode 100644 (file)
index 388fa86..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTButton;
-
-public class ButtonLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public ButtonLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTButton node = parent.addNode(SWTButton.class);
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextContainer_HasText, node.getTextFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Button_Modifier, node.getModifierFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Button_HasImage, node.getImageFunction());
-               
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CComboLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CComboLoader.java.keep
deleted file mode 100644 (file)
index f9a5345..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTCCombo;
-
-public class CComboLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public CComboLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTCCombo node = parent.addNode(SWTCCombo.class);
-               
-        node.setLayoutData(LoaderUtils.getGridData(configuration));
-        node.setStyle(LoaderUtils.getStyle(configuration));
-        
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_AvailableItems, node.getAvailableFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_SelectedItem, node.getSelectionFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_Modifier, node.getModifierFunction());
-        
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ComboLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ComboLoader.java.keep
deleted file mode 100644 (file)
index 036ce94..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTCombo;
-
-public class ComboLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public ComboLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTCombo node = parent.addNode(SWTCombo.class);
-               
-        node.setLayoutData(LoaderUtils.getGridData(configuration));
-        node.setStyle(LoaderUtils.getStyle(configuration));
-        
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_AvailableItems, node.getAvailableFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_SelectedItem, node.getSelectionFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Combo_Modifier, node.getModifierFunction());
-               
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CompositeLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/CompositeLoader.java.keep
deleted file mode 100644 (file)
index 846df84..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.datatypes.literal.RGB;
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTComposite;
-
-public class CompositeLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public CompositeLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTComposite node = parent.addNode(SWTComposite.class);
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasBackground, RGB.Integer.BINDING, node.getBackgroundFunction());
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setLayout(LoaderUtils.getLayout(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               return node;
-
-       }
-
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ExplorerLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ExplorerLoader.java.keep
deleted file mode 100644 (file)
index a767ed9..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.TreeItem;
-import org.simantics.browsing.ui.BuiltinKeys;
-import org.simantics.browsing.ui.NodeContext;
-import org.simantics.databoard.Bindings;
-import org.simantics.db.ReadGraph;
-import org.simantics.db.Resource;
-import org.simantics.db.VirtualGraph;
-import org.simantics.db.WriteGraph;
-import org.simantics.db.common.request.ResourceRead;
-import org.simantics.db.common.request.WriteRequest;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.util.Simantics;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ViewUtils;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTExplorer;
-
-public class ExplorerLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public ExplorerLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, final Variable context) throws DatabaseException {
-               
-               SWTExplorer node = parent.addNode(SWTExplorer.class);
-               
-               node.setStyle(LoaderUtils.getStyle(configuration));
-
-               String browseContextURI = Simantics.getSession().sync(new ResourceRead<String>(configuration) {
-
-                       @Override
-                       public String perform(ReadGraph graph) throws DatabaseException {
-                               ViewsResources VIEW = ViewsResources.getInstance(graph);
-                               Resource browseContext = graph.getSingleObject(resource, VIEW.Explorer_BrowseContext);
-                               return graph.getURI(browseContext);
-                       }
-                       
-               });
-               
-               node.setBrowseContextURI(browseContextURI);
-               
-        node.setLayoutData(LoaderUtils.getGridData(configuration));
-        
-        node.setColumns(LoaderUtils.getColumns(configuration));
-        
-        LoaderUtils.listen(configuration, context, ViewsResources.URIs.Explorer_InputTransformation, node.getInputFunction());
-
-        LoaderUtils.listen(configuration, context, ViewsResources.URIs.Explorer_HasColumnsVisible, node.getColumnsVisibleFunction());
-        
-               Listener selectionListener = Simantics.getSession().sync(new ResourceRead<Listener>(configuration) {
-
-                       @Override
-                       public Listener perform(ReadGraph graph) throws DatabaseException {
-                               ViewsResources VIEW = ViewsResources.getInstance(graph);
-                               Resource listener = graph.getPossibleObject(resource, VIEW.Explorer_SelectionListener);
-                               if(listener == null) return null;
-                               return graph.adapt(listener, Listener.class);
-                       }
-                       
-               });
-               
-               if(selectionListener != null) node.addListenerToControl(SWT.Selection, selectionListener);
-               
-               node.addListenerToControl(SWT.Selection, new Listener() {
-                       
-                       @Override
-                       public void handleEvent(Event event) {
-                               
-                   TreeItem item = (TreeItem)event.item;
-//                 Tree tree = item.getParent();
-//                 GraphExplorer explorer = (GraphExplorer)tree.getData("GraphExplorer");
-//                 final Resource runtimeDiagram = (Resource)explorer.getRoot().getConstant(BuiltinKeys.INPUT);
-//                 final boolean checked = item.getChecked();
-                   NodeContext nc = (NodeContext)item.getData();
-                   Object obj = nc.getConstant(BuiltinKeys.INPUT);
-
-                   if (obj instanceof Variable) {
-                       final Variable var = (Variable) obj;
-                       Simantics.getSession().async(new WriteRequest(Simantics.getSession().getService(VirtualGraph.class)) {
-                           @Override
-                           public void perform(WriteGraph graph) throws DatabaseException {
-                               ViewsResources VIEW = ViewsResources.getInstance(graph);
-                               System.err.println("setParameter " + context.getURI(graph) + " -> " + var.getURI(graph));
-                               ViewUtils.setParameter(graph, context, VIEW.Explorer_Selection, var.getURI(graph), Bindings.STRING);
-                           }
-                       });
-                   }
-                       }
-                       
-               });
-               
-               return node;
-               
-       }
-       
-}
-
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/LabelLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/LabelLoader.java.keep
deleted file mode 100644 (file)
index 53aa17f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTLabel;
-
-public class LabelLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public LabelLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTLabel node = parent.addNode(SWTLabel.class);
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextContainer_HasText, node.getTextFunction());
-               
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ScrolledCompositeLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/ScrolledCompositeLoader.java.keep
deleted file mode 100644 (file)
index 66dcb28..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTScrolledComposite;
-
-public class ScrolledCompositeLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public ScrolledCompositeLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTScrolledComposite node = parent.addNode(SWTScrolledComposite.class);
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setLayout(LoaderUtils.getLayout(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               return node;
-
-       }
-
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TabFolderLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TabFolderLoader.java.keep
deleted file mode 100644 (file)
index 4c6cdf0..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.simantics.db.ReadGraph;
-import org.simantics.db.Resource;
-import org.simantics.db.common.request.UniqueRead;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.util.Simantics;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.db.layer0.variable.Variables;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTTabFolder;
-
-public class TabFolderLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public TabFolderLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTTabFolder node = parent.addNode(SWTTabFolder.class);
-               
-               final Collection<Variable> children = LoaderUtils.getChildren(configuration);
-
-               String[] names = Simantics.getSession().sync(new UniqueRead<String[]>() {
-
-                       @Override
-                       public String[] perform(ReadGraph graph) throws DatabaseException {
-                               
-                               String[] result = new String[children.size()];
-
-                               int index = 0;
-                               for(Variable child : children) {
-                                       result[index++] = child.getPropertyValue(graph, Variables.LABEL);
-                               }
-                               
-                               return result;
-                               
-                       }
-                       
-               });
-               
-               node.setTabNames(names);
-               
-               return node;
-               
-       }
-
-       Set<Control> getControls(CTabItem item) {
-               HashSet<Control> result = new HashSet<Control>();
-               forControl(item.getControl(), result);
-               return result;
-       }
-       
-       void forControl(Control control, HashSet<Control> controls) {
-               controls.add(control);
-               if(control instanceof Composite) {
-                       Composite composite = (Composite)control;
-                       for(Control child : composite.getChildren()) forControl(child, controls);
-               }
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TextLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TextLoader.java.keep
deleted file mode 100644 (file)
index 0141715..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.datatypes.literal.Font;
-import org.simantics.datatypes.literal.RGB;
-import org.simantics.db.Resource;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTText;
-
-public class TextLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public TextLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, Variable context) throws DatabaseException {
-               
-               SWTText node = parent.addNode(SWTText.class);
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextContainer_HasText, node.getTextFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasBackground, RGB.Integer.BINDING, node.getBackgroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasForeground, RGB.Integer.BINDING, node.getForegroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasFont, Font.BINDING, node.getFontFunction());
-        
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TrackedTextLoader.java.keep b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/loader/TrackedTextLoader.java.keep
deleted file mode 100644 (file)
index 699f8ee..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.simantics.views.swt.loader;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.datatypes.literal.Font;
-import org.simantics.datatypes.literal.RGB;
-import org.simantics.db.Resource;
-import org.simantics.db.VirtualGraph;
-import org.simantics.db.WriteGraph;
-import org.simantics.db.common.request.WriteRequest;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.util.Simantics;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.scenegraph.ParentNode;
-import org.simantics.scenegraph.loader.ScenegraphLoader;
-import org.simantics.utils.ui.widgets.TrackedModifyEvent;
-import org.simantics.utils.ui.widgets.TrackedModifyListener;
-import org.simantics.views.ViewUtils;
-import org.simantics.views.ontology.ViewsResources;
-import org.simantics.views.swt.client.base.ISWTViewNode;
-import org.simantics.views.swt.client.impl.SWTTrackedText;
-
-public class TrackedTextLoader implements ScenegraphLoader {
-
-       final private Resource configuration;
-       
-       public TrackedTextLoader(Resource configuration) {
-               this.configuration = configuration;
-       }
-       
-       @Override
-       public ISWTViewNode create(ParentNode<ISWTViewNode> parent, final Variable context) throws DatabaseException {
-               
-               SWTTrackedText node = parent.addNode(SWTTrackedText.class);
-               
-               node.setLayoutData(LoaderUtils.getGridData(configuration));
-               node.setStyle(LoaderUtils.getStyle(configuration));
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextContainer_HasText, node.getTextFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasForeground, RGB.Integer.BINDING, node.getForegroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TrackedText_HasInvalidBackground, RGB.Integer.BINDING, node.getInvalidBackgroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TrackedText_HasInactiveBackground, RGB.Integer.BINDING, node.getInactiveBackgroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TrackedText_HasHoverBackground, RGB.Integer.BINDING, node.getHoverBackgroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TrackedText_HasEditingBackground, RGB.Integer.BINDING, node.getEditingBackgroundFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.Control_HasFont, Font.BINDING, node.getFontFunction());
-               
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextReceiver_Modifier, node.getModifierFunction());
-               LoaderUtils.listen(configuration, context, ViewsResources.URIs.TextReceiver_Validator, node.getValidatorFunction());
-               
-               node.addModifyListener(new TrackedModifyListener() {
-                       
-                       @Override
-                       public void modifyText(TrackedModifyEvent e) {
-                               
-                               final String text = e.getText();
-                   
-                   Simantics.getSession().async(new WriteRequest(Simantics.getSession().getService(VirtualGraph.class)) {
-
-                                       @Override
-                                       public void perform(WriteGraph graph) throws DatabaseException {
-                                               ViewsResources VIEW = ViewsResources.getInstance(graph);
-                                               System.err.println("setParameter " + context.getURI(graph) + " -> " + text);
-                                   ViewUtils.setParameter(graph, context, VIEW.TrackedText_Content, text, Bindings.STRING);
-                                       }
-                       
-                   });
-                               
-                       }
-                       
-               });
-               
-               return node;
-               
-       }
-       
-}
diff --git a/bundles/org.simantics.views.text.ontology/.classpath b/bundles/org.simantics.views.text.ontology/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.views.text.ontology/.project b/bundles/org.simantics.views.text.ontology/.project
new file mode 100644 (file)
index 0000000..7750c6c
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.views.text.ontology</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.simantics.graph.builder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+               <nature>org.simantics.graph.nature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.views.text.ontology/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.views.text.ontology/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..295926d
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8\r
+org.eclipse.jdt.core.compiler.compliance=1.8\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.8\r
diff --git a/bundles/org.simantics.views.text.ontology/META-INF/MANIFEST.MF b/bundles/org.simantics.views.text.ontology/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..6d858cb
--- /dev/null
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: http://www.simantics.org/TextViews
+Bundle-SymbolicName: org.simantics.views.text.ontology
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: Semantum Oy
+Require-Bundle: org.simantics.layer0,
+ org.simantics.views.ontology;bundle-version="1.2.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/bundles/org.simantics.views.text.ontology/build.properties b/bundles/org.simantics.views.text.ontology/build.properties
new file mode 100644 (file)
index 0000000..fb16427
--- /dev/null
@@ -0,0 +1,6 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               graph.tg\r
+src.includes = graph/\r
diff --git a/bundles/org.simantics.views.text.ontology/graph.tg b/bundles/org.simantics.views.text.ontology/graph.tg
new file mode 100644 (file)
index 0000000..5c3d7db
Binary files /dev/null and b/bundles/org.simantics.views.text.ontology/graph.tg differ
diff --git a/bundles/org.simantics.views.text.ontology/graph/TextViews.pgraph b/bundles/org.simantics.views.text.ontology/graph/TextViews.pgraph
new file mode 100644 (file)
index 0000000..6a9c846
--- /dev/null
@@ -0,0 +1,7 @@
+L0 = <http://www.simantics.org/Layer0-1.1>
+VIEWS = <http://www.simantics.org/Views-1.2>
+
+TEXTVIEWS = <http://www.simantics.org/TextViews-1.0> : L0.Ontology
+    @L0.new
+
+TEXTVIEWS.MarkupSourceViewer <T VIEWS.StyledText
diff --git a/bundles/org.simantics.views.text.ontology/src/.keep b/bundles/org.simantics.views.text.ontology/src/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/bundles/org.simantics.views.text/.classpath b/bundles/org.simantics.views.text/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.views.text/.project b/bundles/org.simantics.views.text/.project
new file mode 100644 (file)
index 0000000..f3bb00f
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.views.text</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.simantics.views.text/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.views.text/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..295926d
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8\r
+org.eclipse.jdt.core.compiler.compliance=1.8\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.8\r
diff --git a/bundles/org.simantics.views.text/META-INF/MANIFEST.MF b/bundles/org.simantics.views.text/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..6e60a5a
--- /dev/null
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Modelled Text Viewer UI Controls
+Bundle-SymbolicName: org.simantics.views.text;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.views.text.internal.Activator
+Bundle-Vendor: Semantum Oy
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.editors;bundle-version="3.9.0",
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text;bundle-version="3.10.0",
+ org.eclipse.mylyn.wikitext.core;bundle-version="2.7.0",
+ org.eclipse.mylyn.wikitext.mediawiki.core;bundle-version="2.7.0",
+ org.eclipse.mylyn.wikitext.ui;bundle-version="2.7.0",
+ org.eclipse.mylyn.wikitext.mediawiki.ui;bundle-version="2.7.0",
+ org.simantics.views;bundle-version="1.1.0",
+ org.simantics.views.swt;bundle-version="1.0.0",
+ org.simantics.views.swt.client;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.simantics.views.text/adapters.xml b/bundles/org.simantics.views.text/adapters.xml
new file mode 100644 (file)
index 0000000..c6dbeee
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (c) 2017 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:
+        Semantum Oy - initial API and implementation
+ -->
+<adapters>
+
+       <target interface="org.simantics.scenegraph.loader.ScenegraphLoader">
+               <type uri="http://www.simantics.org/TextViews-0.0/MarkupSourceViewer" class="org.simantics.scenegraph.loader.StandardScenegraphLoader">
+                       <this/>
+                       <bundle />
+                       <string>org.simantics.views.text.internal.SWTMarkupSourceViewer</string>
+               </type>
+       </target>
+
+</adapters>
diff --git a/bundles/org.simantics.views.text/build.properties b/bundles/org.simantics.views.text/build.properties
new file mode 100644 (file)
index 0000000..1ec5e34
--- /dev/null
@@ -0,0 +1,6 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               adapters.xml,\\r
+               plugin.xml\r
diff --git a/bundles/org.simantics.views.text/plugin.xml b/bundles/org.simantics.views.text/plugin.xml
new file mode 100644 (file)
index 0000000..d2c9091
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+    Copyright (c) 2017 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:
+        Semantum Oy - (#7066) undo/redo support for markup editor
+ -->
+
+<plugin>
+
+   <extension
+         point="org.eclipse.core.expressions.definitions">
+      <definition
+            id="org.simantics.views.text.inTextViewer">
+         <with variable="activeFocusControlId">
+            <equals value="inTextViewer"/>
+         </with>
+      </definition>
+   </extension>
+
+   <extension
+         point="org.eclipse.ui.handlers">
+      <handler
+            class="org.simantics.views.text.internal.TextViewerUndoHandler:undo"
+            commandId="org.eclipse.ui.edit.undo">
+         <activeWhen>
+            <reference definitionId="org.simantics.views.text.inTextViewer" />
+         </activeWhen>
+      </handler>
+      <handler
+            class="org.simantics.views.text.internal.TextViewerUndoHandler:redo"
+            commandId="org.eclipse.ui.edit.redo">
+         <activeWhen>
+            <reference definitionId="org.simantics.views.text.inTextViewer" />
+         </activeWhen>
+      </handler>
+   </extension>
+
+</plugin>
diff --git a/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/Activator.java b/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/Activator.java
new file mode 100644 (file)
index 0000000..e0ee562
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.views.text.internal;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class Activator extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.simantics.views.text"; //$NON-NLS-1$
+
+       // The shared instance
+       private static Activator plugin;
+       
+       /**
+        * The constructor
+        */
+       public Activator() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        *
+        * @return the shared instance
+        */
+       public static Activator getDefault() {
+               return plugin;
+       }
+
+}
diff --git a/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/SWTMarkupSourceViewer.java b/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/SWTMarkupSourceViewer.java
new file mode 100644 (file)
index 0000000..756dfe2
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - (#7066) initial API and implementation
+ *******************************************************************************/
+package org.simantics.views.text.internal;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.mylyn.wikitext.core.parser.markup.MarkupLanguage;
+import org.eclipse.mylyn.wikitext.mediawiki.core.MediaWikiLanguage;
+import org.eclipse.mylyn.wikitext.ui.editor.MarkupSourceViewer;
+import org.eclipse.mylyn.wikitext.ui.editor.MarkupSourceViewerConfiguration;
+import org.eclipse.mylyn.wikitext.ui.editor.ShowInTargetBridge;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.services.IServiceLocator;
+import org.eclipse.ui.swt.IFocusService;
+import org.simantics.views.ViewUtils;
+import org.simantics.views.swt.client.base.SingleSWTViewNode;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class SWTMarkupSourceViewer extends SingleSWTViewNode<StyledText> {
+
+       private static final long serialVersionUID = 3034624586096417826L;
+
+       private MarkupSourceViewer viewer;
+       private boolean textInitialized = false;
+
+       @Override
+       public void createControls(Composite parent) {
+               MarkupLanguage language = new MediaWikiLanguage();
+               viewer = new MarkupSourceViewer(parent, null, style | SWT.WRAP, language);
+               viewer.setEditable(false);
+               MarkupSourceViewerConfiguration configuration = new MarkupSourceViewerConfiguration(Activator.getDefault().getPreferenceStore());
+               configuration.setMarkupLanguage(language);
+               configuration.setShowInTarget(new ShowInTargetBridge(viewer));
+               viewer.configure(configuration);
+               viewer.setDocument(new Document(text != null ? text : ""));
+               control = viewer.getTextWidget();
+               control.setData(TextViewerConstants.KEY_UNDO_MANAGER, viewer.getUndoManager());
+               control.setEnabled(false);
+
+               setProperties();
+
+               // Allow undo/redo handler to be bound to this text editor's focus
+               IServiceLocator locator = getSite();
+               if (locator != null) {
+                       IFocusService focusService = locator.getService(IFocusService.class);
+                       if (focusService != null) {
+                               focusService.addFocusTracker(control, TextViewerConstants.CONTEXT_IN_TEXT_VIEWER);
+                       }
+               }
+
+               control.addSelectionListener(new SelectionListener() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               ViewUtils.setWorkbenchSelection(viewer.getSelection());
+                       }
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               widgetSelected(e);
+                       }
+               });
+       }
+
+       @Override
+       public void synchronizeText(String text) {
+               this.text = text;
+               if (text != null) {
+                       // Try to keep the vertical scroll position of the text widget
+                       int caretOffset = control.getCaretOffset();
+                       int charCount = control.getCharCount();
+                       int topIndex = viewer.getTopIndex();
+                       int diff = text.length() - charCount;
+                       int newCaretOffset = Math.max(0, Math.min(caretOffset + diff, text.length()));
+
+                       viewer.getDocument().set(text);
+                       viewer.setTopIndex(topIndex);
+                       control.setCaretOffset(newCaretOffset);
+                       viewer.setEditable(true);
+                       control.setEnabled(true);
+
+                       // Prevent text viewer undo from allowing the
+                       // user to undo the text viewer back to empty.
+                       if (!textInitialized) {
+                               viewer.getUndoManager().reset();
+                               textInitialized = true;
+                       }
+               } else {
+                       textInitialized = false;
+                       viewer.setEditable(false);
+                       control.setEnabled(false);
+                       viewer.getDocument().set("");
+                       viewer.getUndoManager().reset();
+               }
+       }
+
+       public String readText() {
+               return viewer.getDocument().get();
+       }
+
+       public Point readSelection() {
+               return control.getSelection();
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerConstants.java b/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerConstants.java
new file mode 100644 (file)
index 0000000..2924dc3
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - (#7066) initial API and implementation
+ *******************************************************************************/
+package org.simantics.views.text.internal;
+
+import org.eclipse.jface.text.IUndoManager;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.28.0
+ */
+public class TextViewerConstants {
+
+       /**
+        * The UI focus control context used for enabling normal text undo/redo for
+        * {@link TextViewer} controls.
+        */
+       public static final String CONTEXT_IN_TEXT_VIEWER = "inTextViewer";
+
+       /**
+        * A key used for storing an {@link IUndoManager} as data of a
+        * {@link Control} using {@link Control#setData(String, Object)}.
+        */
+       public static final String KEY_UNDO_MANAGER = "undoManager";
+
+}
diff --git a/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerUndoHandler.java b/bundles/org.simantics.views.text/src/org/simantics/views/text/internal/TextViewerUndoHandler.java
new file mode 100644 (file)
index 0000000..f1c8ade
--- /dev/null
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ *     Semantum Oy - (#7066) initial API and implementation
+ *******************************************************************************/
+package org.simantics.views.text.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.jface.text.IUndoManager;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Handles the undo/redo command for {@link TextViewer}s through
+ * {@link IUndoManager}.
+ * 
+ * <p>
+ * The implementation looks for an IUndoManager from the current focus control
+ * using the {@link TextViewerConstants#KEY_UNDO_MANAGER} data key. Its
+ * existence determines whether this handler {@link #isHandled()} returns
+ * <code>true</code> or <code>false</code>.
+ *
+ * <p>
+ * The handler expects to receive a single string as an argument through the
+ * extension definitions ({@link IExecutableExtension}) that determines which
+ * method is invoked from IUndoManager (<code>undo</code> or <code>redo</code>).
+ * 
+ * <p>
+ * Implementation is partially copied from
+ * <code>org.eclipse.ui.internal.handlers.WidgetMethodHandler</code>.
+ * 
+ * @since 1.28.0
+ */
+public class TextViewerUndoHandler extends AbstractHandler implements IExecutableExtension {
+
+       /**
+        * The parameters to pass to the method this handler invokes. This handler
+        * always passes no parameters.
+        */
+       protected static final Class<?>[] NO_PARAMETERS = new Class[0];
+
+       public TextViewerUndoHandler() {
+               display = Display.getCurrent();
+               if (display != null) {
+                       focusListener = new Listener() {
+                               @Override
+                               public void handleEvent(Event event) {
+                                       updateEnablement();
+                               }
+                       };
+                       display.addFilter(SWT.FocusIn, focusListener);
+               }
+       }
+
+       void updateEnablement() {
+               boolean rc = isHandled();
+               if (rc != isEnabled()) {
+                       setBaseEnabled(rc);
+               }
+       }
+
+       /**
+        * The name of the method to be invoked by this handler. This value should
+        * never be <code>null</code>.
+        */
+       protected String methodName;
+       private Listener focusListener;
+       private Display display;
+
+       @Override
+       public Object execute(final ExecutionEvent event) throws ExecutionException {
+               Callable<?> runnable = getMethodToExecute();
+               if (runnable != null) {
+                       try {
+                               runnable.call();
+                       } catch (ExecutionException e) {
+                               throw e;
+                       } catch (Exception e) {
+                               throw new ExecutionException("Unexpected failure executing method " + methodName + " through " + runnable);
+                       }
+               }
+               return null;
+       }
+
+       @Override
+       public final boolean isHandled() {
+               return getMethodToExecute() != null;
+       }
+
+       /**
+        * Looks up the method on the focus control.
+        *
+        * @return The method on the focus control; <code>null</code> if none.
+        */
+       protected Callable<Boolean> getMethodToExecute() {
+               Display display = Display.getCurrent();
+               if (display == null)
+                       return null;
+
+               Control focusControl = display.getFocusControl();
+               if (focusControl == null)
+                       return null;
+
+               IUndoManager undoManager = (IUndoManager) focusControl.getData(TextViewerConstants.KEY_UNDO_MANAGER);
+               if (undoManager == null)
+                       return null;
+
+               try {
+                       Method method = undoManager.getClass().getMethod(methodName, NO_PARAMETERS);
+                       if (method != null)
+                               return runner(undoManager, method);
+               } catch (NoSuchMethodException e) {
+                       //      Fall through...
+               }
+
+               return null;
+       }
+
+       protected Callable<Boolean> runner(IUndoManager undoManager, Method method) {
+               return () -> {
+                       try {
+                               method.invoke(undoManager);
+                               return true;
+                       } catch (IllegalAccessException e) {
+                               // The method is protected, so do nothing.
+                               return false;
+                       } catch (InvocationTargetException e) {
+                               throw new ExecutionException(
+                                               "An exception occurred while executing " //$NON-NLS-1$
+                                                               + method.getName(), e
+                                                               .getTargetException());
+
+                       }
+               };
+       }
+
+       @Override
+       public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+               methodName = data.toString();
+       }
+
+       @Override
+       public void dispose() {
+               if (display != null && !display.isDisposed()) {
+                       display.removeFilter(SWT.FocusIn, focusListener);
+               }
+               display = null;
+               focusListener = null;
+       }
+
+}
\ No newline at end of file
index eba35a5715748ace20ead2fd7ed4e8ce0ca67083..492fd1928ef89ab1632f3fe0a792b5c17f4af89f 100644 (file)
@@ -16,5 +16,11 @@ import com.lowagie.text.DocumentException;
 import com.lowagie.text.pdf.PdfWriter;
 
 public interface IExportable {
-       public void export(Document doc, PdfWriter writer) throws DocumentException;
+       /**
+        * @param doc
+        * @param writer
+        * @return the amount of PDF pages exported
+        * @throws DocumentException
+        */
+       public int export(Document doc, PdfWriter writer) throws DocumentException;
 }
index 68a1b4c50e986f6a0f9d559ea6aeeda3b3f5cc4c..caca38320033554835c7dea616b85f5e7873232b 100644 (file)
Binary files a/bundles/org.simantics.workbench.ontology/graph.tg and b/bundles/org.simantics.workbench.ontology/graph.tg differ
index aa528a652204234ec7358bf57bfaa0b9a03dedd0..7cc4cf4735312ffc5dc90f60e38e85931d0872d1 100644 (file)
@@ -120,6 +120,7 @@ public class OntologyImportAdvisor extends AbstractImportAdvisor2 {
                graph.claim(ontologyName, L0.InstanceOf, null, L0.String);
                graph.claimValue(ontologyName, name, WriteBindings.STRING);
                graph.claim(ontology, L0.HasName, L0.NameOf, ontologyName);
+               graph.claim(ontology, L0.PartOf, L0.ConsistsOf, parent);
                return ontology;
                
         } else {
index cf4928fe793e1088d2c28da8587b9ad538d3f370..d5b223460a0b1d74068f31585873db4e94ba9a20 100644 (file)
@@ -83,6 +83,7 @@ import org.simantics.graph.db.GraphDependencyAnalyzer;
 import org.simantics.graph.db.GraphDependencyAnalyzer.IU;
 import org.simantics.graph.db.GraphDependencyAnalyzer.IdentityNode;
 import org.simantics.graph.db.IImportAdvisor;
+import org.simantics.graph.db.ImportResult;
 import org.simantics.graph.db.TransferableGraphs;
 import org.simantics.graph.diff.Diff;
 import org.simantics.graph.diff.TransferableGraphDelta1;
@@ -107,6 +108,7 @@ import org.simantics.project.management.WorkspaceUtil;
 import org.simantics.utils.FileUtils;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.logging.TimeLogger;
+import org.simantics.utils.strings.EString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -408,7 +410,10 @@ public class SimanticsPlatform implements LifecycleListener {
 
                                        // Install TG
                                        log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Installing "+tg.toString()+" - "+tg.getName()));
-                                       TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null);
+                                       ImportResult result = TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null);
+                                       if (!result.missingExternals.isEmpty()) {
+                                               log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import of " + tg.toString() + " was missing the following external entities:\n" + EString.implode(result.missingExternals)));
+                                       }
                                } else {
                                        // Merge TG
                                        startTransaction(session, false);
index bbc378243b66bab2235f9e7ebf267606540cecae..319859a65adec37394dc44acbc074373e3040d1a 100644 (file)
         <module>org.simantics.views.ontology</module>
         <module>org.simantics.views.swt</module>
         <module>org.simantics.views.swt.client</module>
+        <module>org.simantics.views.text</module>
+        <module>org.simantics.views.text.ontology</module>
         <module>org.simantics.wiki.ui</module>
         <module>org.simantics.workbench</module>
         <module>org.simantics.workbench.ontology</module>
index 48a5e13a5519e21139d2ca1e92bd24b2b9722dbb..9bd6f1eda661db7ee46421d7914ad21322f29b5a 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <feature
-      id="org.simantics.desktop.product"
+      id="org.simantics.desktop.product.feature"
       label="Simantics Desktop Product Feature"
       version="1.0.0.qualifier"
       provider-name="Semantum Oy">
index 791613f1c249a0cddfb41d763cecce18661f2bfe..e54ed961d3950c3493f6207db7c3563bfc4b0979 100644 (file)
          unpack="false"/>
 
    <plugin
-         id="javax.vecmath"
+         id="org.apache.commons.math3"
          download-size="0"
          install-size="0"
          version="0.0.0"
index 1190496c14a5acd81ee788db4fa75f40792189eb..51fab183e724f3de0b6cedea11ffe722a9f892c1 100644 (file)
@@ -13,7 +13,7 @@
 <feature
       id="org.simantics.sdk"
       label="Simantics SDK"
-      version="1.26.0"
+      version="1.29.0"
       provider-name="VTT Technical Research Centre of Finland">
 
    <description url="http://www.example.com/description">
          id="org.simantics.desktop"
          version="0.0.0"/>
 
+   <includes
+         id="org.simantics.desktop.product.feature"
+         version="0.0.0"/>
+
    <plugin
          id="org.simantics.fileimport"
          download-size="0"
index dfa20f265dd3b23f97fcda08e4b721993edac93b..b234acd5cc5bf988c7073d2c48370e383fecb052 100644 (file)
          version="0.0.0"
          unpack="false"/>
 
+  <plugin
+         id="org.eclipse.jetty.http"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.server"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.servlet"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.util"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.io"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.security"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.ui.cheatsheets"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.servlet"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
index 17247686e643750544124dc2c5ccd757cfae4cad..41508ef1c207055bc8961c79055645bf097d3fac 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <feature
       id="org.simantics.views.swt.feature"
-      label="SWT views"
+      label="Modelled SWT Views"
       version="1.0.1.qualifier"
       provider-name="Semantum Oy">
 
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.simantics.views.text"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.views.text.ontology"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
index 6f2597dbf2e69cb4b249690ef4436625ea941bd1..e9b0252675badcee6796bf71e82f0947d8321810 100644 (file)
         <module>org.simantics.db.client.feature</module>
         <module>org.simantics.db.services.feature</module>
         <module>org.simantics.desktop.feature</module>
+        <module>org.simantics.desktop.product.feature</module>
         <module>org.simantics.document.base.feature</module>
         <module>org.simantics.document.linking.feature</module>
         <module>org.simantics.document.swt.feature</module>
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index ae2a64d..de255c2
@@ -1,9 +1,13 @@
 #!/bin/bash
 
+if [ $# -lt 3 ]; then
+       echo "Usage: $0 <major> <minor> <service>"
+       exit -1
+fi
 
-major=1
-minor=25
-service=0
+major=$1
+minor=$2
+service=$3
 ver=${major}.${minor}.${service}
 
 mkdir ${ver}
@@ -19,3 +23,7 @@ IFS=$OLDIFS
 cd ..
 tar zcvf ${ver}.tar.gz ${ver}
 rm -rf ${ver}
+
+echo "Packing up mediawiki sites"
+tar zcvf ${ver}-dev-site.tar.gz /var/www/http-dev.simantics.org/
+tar zcvf ${ver}-enduser-site.tar.gz /var/www/https-www.simantics.org/end_user_wiki/
index 757a7a2e454d452ee319bfa9ede0fd8d7600e77d..6f0fd975306c2bdf486efac5ef01c1ca685c0247 100644 (file)
@@ -375,10 +375,14 @@ git checkout release/x.y.z[.w]
 <li><code>simantics.target</code></li>
 <li><code>org.simantics.sdk.build.targetdefinition.target</code></li>
 </ul>
-<p>At the beginning of simantics.target file, increment <code>sequenceNumber</code> by 1</p>
+<p>At the beginning of simantics.target file, increment <code>sequenceNumber</code> by 1 and replace
+the version numbers in target name and <code>org.simantics.sdk.feature.group</code> and
+<code>org.simantics.sdk.source.feature.group</code> with <code>x.y.z[.w]</code>:</p>
 <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
 &lt;?pde version=&quot;3.8&quot;?&gt;
 &lt;target name=&quot;Simantics x.y.z[.w]&quot; sequenceNumber=&quot;11&quot;&gt;
+&lt;unit id=&quot;org.simantics.sdk.feature.group&quot; version=&quot;x.y.z[.w]&quot;/&gt;
+&lt;unit id=&quot;org.simantics.sdk.source.feature.group&quot; version=&quot;x.y.z[.w]&quot;/&gt;
 </code></pre>
 <p>Next, replace the following rows in both mentioned files:</p>
 <pre><code>&lt;repository location=&quot;http://www.simantics.org/download/master/sdk&quot;/&gt;
@@ -391,6 +395,17 @@ git checkout release/x.y.z[.w]
 &lt;repository location=&quot;http://www.simantics.org/download/release/x.y.z[.w]/external-components/manual&quot;/&gt;
 </code></pre>
 </li>
+<li>
+<p>Edit version number of `org.simantics.sdk` feature in `features/org.simantics.sdk.feature/feature.xml` to `x.y.z[.w]`.</p>
+<pre><code>
+&lt;feature
+      id=&quot;org.simantics.sdk&quot;
+      label=&quot;Simantics SDK&quot;
+      version=&quot;x.y.z&quot;
+      provider-name=&quot;VTT Technical Research Centre of Finland&quot;&gt;
+</code></pre>
+<p>Now commit and push the changes to the release branch.</p>
+</li>
 </ol>
 <h3>Initialize release branch distribution web site</h3>
 <ul>
index 3ce2a0c691577b6ea97d6c41d8424097bd415b27..6d55c144db228408b2b2daf2aa1bf96a6b41ade9 100644 (file)
@@ -84,11 +84,15 @@ With service releases, branch from an existing `release/*` branch instead.
    * `simantics.target`
    * `org.simantics.sdk.build.targetdefinition.target`
 
-   At the beginning of simantics.target file, increment `sequenceNumber` by 1
+   At the beginning of simantics.target file, increment `sequenceNumber` by 1 and replace
+   the version numbers in target name and `org.simantics.sdk.feature.group` and
+   `org.simantics.sdk.source.feature.group` with `x.y.z[.w]`:
    ~~~
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <?pde version="3.8"?>
    <target name="Simantics x.y.z[.w]" sequenceNumber="11">
+   <unit id="org.simantics.sdk.feature.group" version="x.y.z[.w]"/>
+   <unit id="org.simantics.sdk.source.feature.group" version="x.y.z[.w]"/>
    ~~~
 
    Next, replace the following rows in both mentioned files:   
@@ -107,6 +111,15 @@ With service releases, branch from an existing `release/*` branch instead.
    <repository location="http://www.simantics.org/download/release/x.y.z[.w]/external-components/manual"/>
    ~~~
 
+3. Edit version number of `org.simantics.sdk` feature in `features/org.simantics.sdk.feature/feature.xml` to `x.y.z[.w]`.
+   ~~~
+   <feature
+         id="org.simantics.sdk"
+         label="Simantics SDK"
+         version="x.y.z"
+         provider-name="VTT Technical Research Centre of Finland">
+   ~~~
+
 ### Initialize release branch distribution web site
 
 * Run [SDK/Deploy External Components to Web](https://www.simantics.org/jenkins/job/SDK/job/Deploy%20External%20Components%20to%20Web/) build with parameters:
diff --git a/releng/org.simantics.desktop.rcp.product/.project b/releng/org.simantics.desktop.rcp.product/.project
new file mode 100644 (file)
index 0000000..2ff298b
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.desktop.rcp.product</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+       </buildSpec>\r
+       <natures>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/releng/org.simantics.desktop.rcp.product/pom.xml b/releng/org.simantics.desktop.rcp.product/pom.xml
new file mode 100644 (file)
index 0000000..ccee592
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>org.simantics</groupId>
+       <artifactId>org.simantics.desktop.rcp.product</artifactId>
+       <version>1.0.0-SNAPSHOT</version>
+       <packaging>eclipse-repository</packaging>
+       
+       <parent>
+               <groupId>org.simantics</groupId>
+               <artifactId>org.simantics.root.releng</artifactId>
+               <version>1.0.0-SNAPSHOT</version>
+       </parent>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.eclipse.tycho</groupId>
+                               <artifactId>tycho-p2-repository-plugin</artifactId>
+                               <version>${tycho.version}</version>
+                               <configuration>
+                                       <includeAllDependencies>true</includeAllDependencies>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.eclipse.tycho</groupId>
+                               <artifactId>tycho-p2-director-plugin</artifactId>
+                               <version>${tycho.version}</version>
+                               <executions>
+                                       <execution>
+                                               <id>materialize-products</id>
+                                               <goals>
+                                                       <goal>materialize-products</goal>
+                                               </goals>
+                                       </execution>
+                                       <execution>
+                                               <id>archive-products</id>
+                                               <goals>
+                                                       <goal>archive-products</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
similarity index 66%
rename from bundles/org.simantics.desktop.product/simantics-desktop.product
rename to releng/org.simantics.desktop.rcp.product/simantics-desktop.product
index 892730d370c9364a37d21186d05abbd87110bf31..f68f507c00a44f41d37bc60edaa05d3d77a850b5 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?pde version="3.5"?>
 
-<product name="Simantics Desktop" uid="org.simantics.desktop.product.desktopProduct" id="org.simantics.desktop.product.desktopProduct" application="org.simantics.workbench.application" version="1.21.0" useFeatures="true" includeLaunchers="true">
+<product name="Simantics Desktop" uid="Simantics-Desktop" id="org.simantics.desktop.product.desktopProduct" application="org.simantics.workbench.application" version="1.28.0" useFeatures="true" includeLaunchers="true">
 
    <aboutInfo>
       <image path="/org.simantics.desktop.ui/icons/simantics256.png"/>
@@ -57,7 +57,7 @@ org.eclipse.e4.ui.css.theme.e4_classic
    </plugins>
 
    <features>
-      <feature id="org.simantics.desktop.product" version="1.0.0.qualifier"/>
+      <feature id="org.simantics.desktop.product.feature" version="1.0.0.qualifier"/>
    </features>
 
 
@@ -67,5 +67,13 @@ org.eclipse.e4.ui.css.theme.e4_classic
 
    <cssInfo>
    </cssInfo>
+   
+   <configurations>
+      <plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" />
+      <plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" />
+      <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" />
+      <plugin id="org.eclipse.equinox.p2.reconciler.dropins" autoStart="true" startLevel="5" />
+      <plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" />
+   </configurations>
 
 </product>
index 404103dcdaa8516c3eed2e8732f74c426d7ed107..b8d6a714fdbbc7e13a4576976caa0cb01a6f1042 100644 (file)
@@ -13,6 +13,8 @@
         <lucene.version>4.9.0</lucene.version>
         <lucene.version.actual>4.9.0.b0003</lucene.version.actual>
         <lucene.prefix>org.apache.lucene4</lucene.prefix>
+        <jdom.version>2.0.6</jdom.version>
+        <jdom.version.actual>2.0.6.b0001</jdom.version.actual>
     </properties>
 
 
                                     </instructions>
                                 </artifact>
                                 <artifact>
-                                    <id>org.jdom:jdom2:2.0.6</id>
+                                    <id>org.jdom:jdom2:${jdom.version}</id>
                                     <source>true</source>
                                     <instructions>
                                         <Bundle-SymbolicName>org.jdom2</Bundle-SymbolicName>
+                                        <Bundle-Version>${jdom.version.actual}</Bundle-Version>
+                                        <Export-Package>*;version="${jdom.version}"</Export-Package>
                                     </instructions>
                                 </artifact>
                                 <artifact>
                                         <Bundle-Version>${itext.version.actual}</Bundle-Version>
                                     </instructions>
                                 </artifact>
-                                <artifact>
-                                    <id>javax.vecmath:vecmath:1.5.2</id>
-                                    <transitive>false</transitive>
-                                    <override>true</override>
-                                    <instructions>
-                                        <Export-Package>javax.vecmath</Export-Package>
-                                    </instructions>
-                                </artifact>
                                 <artifact>
                                     <id>org.mozilla:rhino:1.7.7.1</id>
                                     <source>true</source>
                                 </artifact>
                                 <artifact>
-                                    <id>net.java.dev.jna:jna:4.2.2</id>
+                                    <id>net.java.dev.jna:jna:4.3.0</id>
                                     <source>true</source>
                                 </artifact>
                                 <artifact>
-                                    <id>net.java.dev.jna:jna-platform:4.2.2</id>
+                                    <id>net.java.dev.jna:jna-platform:4.3.0</id>
                                     <source>true</source>
                                 </artifact>
                                 <artifact>
index 5e4173d2a291b3a4b550e136dcae2d76c4393908..d8425c09e52b2372f2887bd73cb14d3f2a724dd3 100644 (file)
 <unit id="com.koloboke.impl-common-jdk8.source" version="1.0.0"/>
 <unit id="com.lowagie.text" version="2.1.7.b1"/>
 <unit id="com.lowagie.text.source" version="2.1.7.b1"/>
-<unit id="com.sun.jna" version="4.2.2"/>
-<unit id="com.sun.jna.source" version="4.2.2"/>
-<unit id="com.sun.jna.platform" version="4.2.2"/>
-<unit id="com.sun.jna.platform.source" version="4.2.2"/>
+<unit id="com.sun.jna" version="4.3.0"/>
+<unit id="com.sun.jna.source" version="4.3.0"/>
+<unit id="com.sun.jna.platform" version="4.3.0"/>
+<unit id="com.sun.jna.platform.source" version="4.3.0"/>
 <unit id="freemarker" version="2.3.23.stable"/>
 <unit id="freemarker.source" version="2.3.23.stable"/>
 <unit id="gnu.trove2" version="2.1.0"/>
 <unit id="it.unimi.dsi.fastutil" version="7.0.13"/>
 <unit id="it.unimi.dsi.fastutil.source" version="7.0.13"/>
 <unit id="jakarta-regexp" version="1.4.0"/>
-<unit id="javax.vecmath" version="1.5.2"/>
 <unit id="net.jcip.annotations" version="1.0.0"/>
 <unit id="net.jcip.annotations.source" version="1.0.0"/>
 <unit id="net.ucanaccess" version="3.0.7"/>
 <unit id="org.eclipse.collections.eclipse-collections.source" version="7.1.0"/>
 <unit id="org.hsqldb.hsqldb" version="2.3.1"/>
 <unit id="org.hsqldb.hsqldb.source" version="2.3.1"/>
-<unit id="org.jdom2" version="2.0.6"/>
-<unit id="org.jdom2.source" version="2.0.6"/>
+<unit id="org.jdom2" version="2.0.6.b0001"/>
+<unit id="org.jdom2.source" version="2.0.6.b0001"/>
 <unit id="org.jfree.jchart" version="1.0.19"/>
 <unit id="org.jfree.jchart.source" version="1.0.19"/>
 <unit id="org.jfree.jcommon" version="1.0.23"/>
index dd3395a297843aa0c549e62c496b43a04c8fc16f..ca20f0fb9986fa044688161397e06b7a182e20de 100644 (file)
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde version="3.8"?>
-<target name="Simantics 1.26.0" sequenceNumber="12">
+<target name="Simantics 1.29.0" sequenceNumber="16">
 <locations>
 <location includeAllPlatforms="true" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
-<unit id="org.simantics.sdk.feature.group" version="1.26.0"/>
-<unit id="org.simantics.sdk.source.feature.group" version="1.26.0"/>
+<unit id="org.simantics.sdk.feature.group" version="1.29.0"/>
+<unit id="org.simantics.sdk.source.feature.group" version="1.29.0"/>
 <repository location="http://www.simantics.org/download/master/sdk"/>
 </location>
 <location includeAllPlatforms="true" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
 <unit id="com.koloboke.impl-common-jdk8.source" version="1.0.0"/>
 <unit id="com.lowagie.text" version="2.1.7.b1"/>
 <unit id="com.lowagie.text.source" version="2.1.7.b1"/>
-<unit id="com.sun.jna" version="4.2.2"/>
-<unit id="com.sun.jna.source" version="4.2.2"/>
-<unit id="com.sun.jna.platform" version="4.2.2"/>
-<unit id="com.sun.jna.platform.source" version="4.2.2"/>
+<unit id="com.sun.jna" version="4.3.0"/>
+<unit id="com.sun.jna.source" version="4.3.0"/>
+<unit id="com.sun.jna.platform" version="4.3.0"/>
+<unit id="com.sun.jna.platform.source" version="4.3.0"/>
 <unit id="freemarker" version="2.3.23.stable"/>
 <unit id="freemarker.source" version="2.3.23.stable"/>
 <unit id="gnu.trove2" version="2.1.0"/>
 <unit id="it.unimi.dsi.fastutil" version="7.0.13"/>
 <unit id="it.unimi.dsi.fastutil.source" version="7.0.13"/>
 <unit id="jakarta-regexp" version="1.4.0"/>
-<unit id="javax.vecmath" version="1.5.2"/>
 <unit id="net.jcip.annotations" version="1.0.0"/>
 <unit id="net.jcip.annotations.source" version="1.0.0"/>
 <unit id="net.ucanaccess" version="3.0.7"/>
 <unit id="org.eclipse.collections.eclipse-collections.source" version="7.1.0"/>
 <unit id="org.hsqldb.hsqldb" version="2.3.1"/>
 <unit id="org.hsqldb.hsqldb.source" version="2.3.1"/>
-<unit id="org.jdom2" version="2.0.6"/>
-<unit id="org.jdom2.source" version="2.0.6"/>
+<unit id="org.jdom2" version="2.0.6.b0001"/>
+<unit id="org.jdom2.source" version="2.0.6.b0001"/>
 <unit id="org.jfree.jchart" version="1.0.19"/>
 <unit id="org.jfree.jchart.source" version="1.0.19"/>
 <unit id="org.jfree.jcommon" version="1.0.23"/>
index e6b89c8d7d44e0d71a8cb26e47939402dc712ed7..b3d1dc628b9bcc7f5dbd38bb934a5b9a34681711 100644 (file)
@@ -2,7 +2,7 @@
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <artifactId>org.simantics.sdk.repository</artifactId>
-       <version>1.26.0-SNAPSHOT</version>
+       <version>1.29.0-SNAPSHOT</version>
        <packaging>eclipse-repository</packaging>
 
        <parent>
index 31243d1e9ee17dbe1e980c7d3f882ca72790cdb6..dd0a01205f9448a55a27fcf973ee3940cb33324c 100644 (file)
@@ -16,5 +16,6 @@
        <modules>
                <module>org.simantics.sdk.build.targetdefinition</module>
                <module>org.simantics.sdk.repository</module>
+               <module>org.simantics.desktop.rcp.product</module>
        </modules>
-</project>
\ No newline at end of file
+</project>
index 4670b048d62f7b19cdfd9cd1abb2e780de486015..82193b4813df7c3f060cdf460f85ed31c67384b7 100644 (file)
@@ -1,7 +1,5 @@
 package org.simantics.scl.compiler.tests;
 
-import org.junit.Test;
-
 public class ActiveTests extends TestBase {
     
     public ActiveTests() { super("scl"); }
@@ -18,7 +16,6 @@ public class ActiveTests extends TestBase {
     @Test public void TypeClassBug2() { test(); }
   */  
     
-    //@Test public void CityoptSetup() { test(); }
+    //@Test public void Bug6989() { test(); }
     
-    @Test public void Bug6989() { test(); }
 }
index 38506c6f4997070d86d72ca1d3f2222cd707445c..cecc93e84c7df47f9f73463697419a38c1993062 100644 (file)
@@ -26,6 +26,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void CHR2() { test(); }
     @Test public void CHR3() { test(); }
     @Test public void CHR4() { test(); }
+    @Test public void ClosureRecursion() { test(); }
     @Test public void Collaz() { test(); }
     @Test public void Compose() { test(); }
     @Test public void Composition() { test(); }
@@ -72,6 +73,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void FromDynamic4() { test(); }
     @Test public void FromDynamic5() { test(); }
     @Test public void FunctionFunctor() { test(); }
+    @Test public void FunctionIdentity() { test(); }
     @Test public void Functor() { test(); }
     @Test public void FunctorM1() { test(); }
     @Test public void Generalization() { test(); }
@@ -135,6 +137,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void LocalDefinitions3() { test(); }
     @Test public void LocalDefinitions4() { test(); }
     @Test public void LocalDefinitions5() { test(); }
+    @Test public void Logger() { test(); }
     @Test public void Macros1() { test(); }
     @Test public void Macros2() { test(); }
     @Test public void Macros4() { test(); }
@@ -224,6 +227,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void StringInterpolation3() { test(); }
     @Test public void StringMatching1() { test(); }
     @Test public void SumOfInverses2() { test(); }
+    @Test public void SwitchSimplification() { test(); }
     @Test public void TooManyParametersToSin() { test(); }
     @Test public void Transformation1() { test(); }
     @Test public void Transformation2() { test(); }
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/ClosureRecursion.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/ClosureRecursion.scl
new file mode 100644 (file)
index 0000000..4b31b1d
--- /dev/null
@@ -0,0 +1,21 @@
+import "Prelude"
+
+countDown :: Ref Integer -> <Proc> Boolean
+countDown r = if currentValue <= 0
+              then False
+              else do 
+                  r := currentValue - 1
+                  True
+  where
+    currentValue = getRef r 
+
+strangeLoop :: (<Proc> Boolean) -> <Proc> ()
+strangeLoop cond = if cond
+                   then strangeLoop cond
+                   else ()
+
+main = do
+    r = ref 100000 :: Ref Integer
+    strangeLoop (countDown r)
+--
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/FunctionIdentity.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/FunctionIdentity.scl
new file mode 100644 (file)
index 0000000..cbf797b
--- /dev/null
@@ -0,0 +1,9 @@
+import "Prelude"
+
+f n = do
+  a = n+1
+  \x -> a + x
+
+main = [atan2 1==atan2 1, atan2 1==atan2 2, f 1==f 1, f 1==f 2]
+--
+[true, false, true, false]
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Logger.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Logger.scl
new file mode 100644 (file)
index 0000000..84a5030
--- /dev/null
@@ -0,0 +1,5 @@
+import "Logging"
+
+main = info "Something happened."
+--
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/SwitchSimplification.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/SwitchSimplification.scl
new file mode 100644 (file)
index 0000000..8ea1d01
--- /dev/null
@@ -0,0 +1,5 @@
+foo () = "asd"
+
+main = foo ()
+--
+asd
\ No newline at end of file