I am working with OleAutomation Java APIs provided by SWT(Standard Widget Toolkit) to manipulate Visio documents. We have generated Java wrappers over automation APIs using OleAutomation calls. for e.g :(shape delete)
/**
* COM Id: 11
*/
public void Delete() {
//Invoke
Variant varInputArray[] = new Variant[0];
Variant varResult = oleAutomation.invoke(11, varInputArray);
for (Variant _varItr : varInputArray) {
_varItr.dispose();
}
if(varResult !=null)
{
varResult.dispose();
}
}
I am facing a peculiar problem when calling this delete from a certain place in the application logic. On a page I place a shape and call delete. For odd numbered calls the delete is successful and the varResult returns VT_EMPTY(1st,3rd,5th.... time call). For even numbered calls (I place the shape again on the page and call -2nd,4th 6th etc) the varResult returns "null" which indicates failure. Now I need to understand what's going wrong with even numbered call. Is there some kind of logging facility in Visio Automation framework which can log the reason for failure ?
Try deleting shapes backwards. I.e. iterate collection backwards when deleting shapes.
That means, instead of:
shapes = Page.Shapes;
foreach (shape : shapes)
{
if (xxx)
shape.Delete()
}
Try this
shapes = Page.Shapes;
for (int i = shapes.Count; i > 0; --i)
{
if (xxx)
shapes[i].Delete()
}
Means, Visio has a bit "naive" collection management, so deleting items from collection while iterating over it may put you in troubles, and should be done carefully, like one would do for an array.
Alternatively, you can first select all shapes to delete and then delete them in one shot:
shapes = Page.shapes;
sel = Page.CreateSelection(visSelTypeEmpty);
foreach (shape : shapes)
{
if (xxx)
sel.Select(shape, visSelect);
}
sel.Delete();
Related
I am running a hierachical Spring Statemachine and - after walking through the inital transitions into state UP with the default substate STOPPED - want to use statemachine.getState(). Trouble is, it gives me only the parent state UP, and I cannot find an obvious way to retrieve both the parent state and the sub state.
The machine has states constructed like so:
StateMachineBuilder.Builder<ToolStates, ToolEvents> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial(ToolStates.UP)
.state(ToolStates.UP, new ToolUpEventAction(), null)
.state(ToolStates.DOWN
.and()
.withStates()
.parent(ToolStates.UP)
.initial(ToolStates.STOPPED)
.state(ToolStates.STOPPED,new ToolStoppedEventAction(), null )
.state(ToolStates.IDLE)
.state(ToolStates.PROCESSING,
new ToolBeginProcessingPartAction(),
new ToolDoneProcessingPartAction());
...
builder.build();
ToolStates and ToolEvents are just enums. In the client class, after running the builder code above, the statemachine is started with statemachine.start(); When I subsequently call statemachine.getState().getId(); it gives me UP. No events sent to statemachine before that call.
I have been up and down the Spring statemachine docs and examples. I know from debugging that the entry actions of both states UP and STOPPED have been invoked, so I am assuming they are both "active" and would want to have both states presented when querying the statemachine. Is there a clean way to achieve this ? I want to avoid storing the substate somewhere from inside the Action classes, since I believe I have delegated all state management issues to the freakin Statemachine in the first place and I would rather like to learn how to use its API for this purpose.
Hopefully this is something embarrasingly obvious...
Any advice most welcome!
The documentation describes getStates():
https://docs.spring.io/spring-statemachine/docs/current/api/org/springframework/statemachine/state/State.html
java.util.Collection<State<S,E>> getStates()
Gets all possible states this state knows about including itself and substates.
stateMachine.getState().getStates();
to wrap it up after SMA's most helpful advice: turns out the stateMachine.getState().getStates(); does in my case return a list of four elements:
a StateMachineState instance containing UP and STOPPED
three ObjectState instances containing IDLE, STOPPED and PROCESSING,
respectively.
this leads me to go forward for the time being with the following solution:
public List<ToolStates> getStates() {
List<ToolStates> result = new ArrayList<>();
Collection<State<ToolStates, ToolEvents>> states = this.stateMachine.getState().getStates();
Iterator<State<ToolStates, ToolEvents>> iter = states.iterator();
while (iter.hasNext()) {
State<ToolStates, ToolEvents> candidate = iter.next();
if (!candidate.isSimple()) {
Collection<ToolStates> ids = candidate.getIds();
Iterator<ToolStates> i = ids.iterator();
while (i.hasNext()) {
result.add(i.next());
}
}
}
return result;
}
This maybe would be more elegant with some streaming and filtering, but does the trick for now. I don't like it much, though. It's a lot of error-prone logic and I'll have to see if it holds in the future - I wonder why there isn't a function in the Spring Statemachine that gives me a list of the enum values of all the currently active states, rather than giving me everything possible and forcing me to poke around in it with external logic...
I have been using SnakeYAML for certain serialization/deserialization. My application combines Python and Java, so I need some "reasonable behaviour" on the Tags and the Types.
My problem / actual status on the YAML document:
!!mypackage.MyClassA
someFirstField: normal string
someSecondField:
a: !!mypackage.ThisIsIt
subField: 1
subOtherField: 2
b: !!mypackage.ThisIsIt
subField: 3
subOtherField: 4
someThirdField:
subField: 5
subOtherField: 6
I achieved the use of the tags inside collections (see example someSecondField) by reimplementing checkGlobalTag and simply performing return. This, if I understood correctly, ensures no smart cleanness of snakeyaml and maintains the tags. So far so good: I need the type everywhere.
However, this is not enough, because someThirdField is also a !!mypackage.ThisIsIt but it has implicit tag and this is a problem (Python does not understand it). There are some other corner cases which are not to the point (tried to take some shortcuts in the Python side, and they became a Bad Idea).
Which is the correct way to ensure that the tags appear for all user-defined classes? I assume that I should override some methods on the Representer, but I have not been able to find which one.
The line responsible for that "smart tag auto-clean" is the following:
if (property.getType() == propertyValue.getClass())
Which can be found in representJavaBeanProperty, for the class Representer.
The (ugly) solution I found is to extend the Representer and #Override the representJavaBeanProperty with the following:
protected NodeTuple representJavaBeanProperty(Object javaBean,
Property property,
Object propertyValue,
Tag customTag) {
// Copy paste starts here...
ScalarNode nodeKey = (ScalarNode) representData(property.getName());
// the first occurrence of the node must keep the tag
boolean hasAlias = this.representedObjects.containsKey(propertyValue);
Node nodeValue = representData(propertyValue);
if (propertyValue != null && !hasAlias) {
NodeId nodeId = nodeValue.getNodeId();
if (customTag == null) {
if (nodeId == NodeId.scalar) {
if (propertyValue instanceof Enum<?>) {
nodeValue.setTag(Tag.STR);
}
}
// Copy-paste ends here !!!
// Ignore the else block --always maintain the tag.
}
}
return new NodeTuple(nodeKey, nodeValue);
This also forces the explicit-tag-on-lists behaviour (previously enforced through the override of the checkGlobalTag method, now already implemented in the representJavaBeanProperty code).
How can I get the list of modified, new, and removed files using org.jenkinsci.plugins.gitclient.GitClient ?
Right now, I'm doing something like:
String status = ((CliGitAPIImpl) gitClient).launchCommand("ls-files", "--deleted", "--modified", "--others", SOME_DIRECTORY);
for (String toCommit : status.split("\\R")) {
gitClient.add(toCommit);
}
but I don't like this approach. first, because it relies on CliGitAPIImpl (and other Jenkins installations could use other classes, like for example RemoteGitImpl which doesn't implement the launchCommand method). second, I'm already using gitClient to create branches, add files to be committed, commit, push, etc., therefore I would prefer to use some API rather than just calling launchCommand method.
--
Thanks,
Jose
I am working on a solution where I need to populate certain fields in a DataObject, though fields are predefined but source from where I need to populate this data is not in my control and I can not do any modification or changes.
This is a structure of my Source Object
SourceObject
-Collection<Features>
-Collection<FeatureData>
Attribute Name is defined in SourceObject which will help me to decided if I want that attribute value or not (There are many attributes (Framework Provided + Custom one)) and Value is being provided from Collection<FeatureData>
for(SourceData sourceData : productData.getSourceData())
{
if(sourceData.getCode().equalsIgnoreCase("classification"))
{
if(CollectionUtils.isNotEmpty(sourceData.getFeatures()))
{
for(FeatureData featureData : sourceData.getFeatures()){
if(CollectionUtils.isNotEmpty(featureData.getFeatureValues())){
if(featureData .getCode().contains("customValue1")){
for(FeatureValueData featureDataValue: featureData.getFeatureValues()){
productData.setPower(featureDataValue.getValue()));
break;
}
}
}
break;
}
}
}
}
But that means I have to do this (Check and Fill) for all my custom attributes. Is there way I can handle it in good way ?.
Please do not pay much attention to syntax or any potential NPE etc, as I will going to take care of those issues
From what I can comprehend from your code is that you are trying to find the very first sourceData whose code matches the "classification" value and also whose features collection isn't empty.
Then once such sourceData is found, you are trying to find the very first feature from the sourceData's features collection whose code contains the "customValue1" in it and whose featureValueData collection isn't empty.
Once such feature is found, you are effectively setting the productData's power as the value that is held by the very first featureValueData of the featureValueData collection of the feature.
Such code can be rewritten as follows:
// Start
SourceData sourceData = findFirstValidSource(productData.getSourceData());
if (sourceData == null) // Can remove this check if sure that at least one valid source data will always exist.
{
return;
}
FeatureData feature = findFirstValidFeature(sourceData.getFeatures());
if (feature == null) // Can also remove this check if sure that at least one valid feature data will always exist.
{
return;
}
FeatureValueData featureValueData = feature.getFeatureValues().iterator().next();
productData.setPower(featureValueData.getValue());
// End
The findFirstValidSource() method is implemented as follows:
private SourceData findFirstValidSource(Collection<SourceData> sources)
{
for (SourceData source : sources)
{
if (source.getCode().equalsIgnoreCase("classification") && CollectionUtils.isNotEmpty(source.getFeatures()))
{
return source;
}
}
return null;
}
The findFirstValidFeature() method is implemented as follows:
private FeatureData findFirstValidFeature(Collection<FeatureData> features)
{
for (FeatureData feature : features)
{
if (feature.getCode().contains("customValue1") && CollectionUtils.isNotEmpty(feature.getFeatureValues()))
{
return feature;
}
}
return null;
}
The above code will also do the exact same thing that your code is doing, except that its more readable and understandable now. The code can save some more processing if you make your getFeatureValues() method return a List instead of a Collection, as then it can grab the very first element through indexing (if implementation is ArrayList based) or by getting the first element (if implementation is LinkedList based), which will take constant time.
Not that the iterator().next() takes any more time, it just is useless to create an iterator in this case when there's no requirement of it as I did in the line:
FeatureValueData featureValueData = feature.getFeatureValues().iterator().next();
If getFeatureValues() would have returned a List, we could have written:
FeatureValueData featureValueData = feature.getFeatureValues().get(0);
instead.
Furthermore, the code can be made more compact by use of Lambda Expressions and Streams which are introduced in JDK 8. If you have no issues using the new features of Java 8, I can update my answer to incorporate a terser solution as well.
Let me know if my answer helped or if your expectations are still not met.
I would like to print multiple pdfs from java (using the java print service) in a single print job.
I would like to send multiple pdfs as a single job to the printer. This is so that all the documents in my 'batch' print together and are not interleaved with someone else's print jobs when I go pick them up from the printer.
A batch potentially consists of 1000s of print jobs.
I tried jpedal, but it does not support java.awt.print.Book
Book book = new Book();
PdfDecoder pdfDecoder = readFileApplyOptions("C:/Temp/singlepagetest.pdf", pageFormat);
book.append(pdfDecoder, pageFormat);
PdfDecoder pdfDecoderTwo = readFileApplyOptions("C:/Temp/printfax-test.pdf",pageFormat);
book.append(pdfDecoderTwo, pageFormat);
printJob.setPageable(book);
printJob.print();
only prints out the first pdf. How do I print multiple pdfs in a single job?
readFileAndApplyOptions() basically creates a new PdfDecoder object and returns it.
I also tried Sun's PDFRenderer PDFRenderer in a similar fashion (using the Book object), but my code still only prints out the first page only.
Has anyone encountered a similar issue before? Is there a solution I might be missing?
Not Java specific, but I've experience of this one in C#. I solved it by printing each document to a file (programmatically equivalent to checking the "PrintToFile" checkbox on a print dialog), then concatenated each file into a memory stream, which I passed to the Win32 API printer spool in raw format (since the output to file was already correctly formatted by default).
You might be able to use a similar technique in Java
I met the same difficulties when printing at once several JPanels of a JTabbedPane, each on a separate page. I gather them in a Book but it only prints the first page.
The Book class works well (right number of pages), but I suppose the problem comes from setPageable. Since a Book is not a Printable, I made it, and it works !
Workaround:
Design a PrintableBook class : extends Book, implements Printable
public class PrintableBook extends Book implements Printable {
Vector<Printable> pages;// NB: we assume pages are single
public PrintableBook() {
super();
pages = new Vector<Printable>();
}
public void add(Printable pp) {
append(pp, pp.getPageFormat());
pages.add(pp);
}
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex >= pages.size())
return NO_SUCH_PAGE;
else {
Printable pp = pages.elementAt(pageIndex);
return pp.print(g, pf, 0);
}
}
}
Then use printJob.setPrintable( printableBook ) instead of setPageable
You should merge all of your pdf documents in one document using iText library and then print the merged document page by page.
see Print a PDF Document in Java
AFAIK, you can't, multiple documents will be printed in multiple jobs.
A workaround could be join all the pdf into a single document and print them.
:-/