Merging two identical word document displaying wrong page number using aspose word - aspose

Using Aspose Implementation:Aspose.Words for Java
Aspose Implementation-Version: 13.5.0.0
Below are the documents:
Source.docx
A1.docx
A2.docx
A3.docx
Using below code to append the word documents:
public static void main(String[] args) {
try {
List<Document> documentsToBeMerged=new ArrayList<Document>();
Document source=new Document("D:/Source.docx");
Document identicalDoc1=new Document("D:/A1.docx");
Document identicalDoc2=new Document("D:/A2.docx");
Document identicalDoc3=new Document("D:/A3.docx");
documentsToBeMerged.add(identicalDoc1);
documentsToBeMerged.add(identicalDoc2);
documentsToBeMerged.add(identicalDoc3);
mergeDocumentsWithSourceDocumentHeaderFooter(source, documentsToBeMerged, "D:/output.docx");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void mergeDocumentsWithSourceDocumentHeaderFooter(
Document destinationDocument, List<Document> mergingdocument,
String outputFileName) throws Exception {
try {
for (Document document : mergingdocument) {
document.getFirstSection().getPageSetup()
.setSectionStart(SectionStart.NEW_PAGE);
document.getFirstSection().getHeadersFooters()
.linkToPrevious(true);
destinationDocument.appendDocument(document,
ImportFormatMode.KEEP_SOURCE_FORMATTING);
}
AsposeUtil.convertNumPageFieldsToPageRef(destinationDocument);
destinationDocument.updatePageLayout();
destinationDocument.save(outputFileName);
} catch (Exception e) {
throw e;
}
}
public static void convertNumPageFieldsToPageRef(Document doc) throws Exception
{
final String BOOKMARK_PREFIX = "_SubDocumentEnd";
final String NUM_PAGES_FIELD_NAME = "NUMPAGES";
final String PAGE_REF_FIELD_NAME = "PAGEREF";
DocumentBuilder builder = new DocumentBuilder(doc);
int subDocumentCount = 0;
for (Section section : doc.getSections())
{
if (section.getPageSetup().getRestartPageNumbering())
{
if (!section.equals(doc.getFirstSection()))
{
Section prevSection = (Section)section.getPreviousSibling();
Node lastNode = prevSection.getBody().getLastChild();
builder.moveTo(lastNode);
builder.startBookmark(BOOKMARK_PREFIX + subDocumentCount);
builder.endBookmark(BOOKMARK_PREFIX + subDocumentCount);
subDocumentCount++;
}
}
if (section.equals(doc.getLastSection()))
{
Node lastNode = doc.getLastSection().getBody().getLastChild();
builder.moveTo(lastNode);
builder.startBookmark(BOOKMARK_PREFIX + subDocumentCount);
builder.endBookmark(BOOKMARK_PREFIX + subDocumentCount);
}
for (Node node : section.getChildNodes(NodeType.FIELD_START, true).toArray())
{
FieldStart fieldStart = (FieldStart)node;
if (fieldStart.getFieldType() == FieldType.FIELD_NUM_PAGES)
{
String fieldCode = getFieldCode(fieldStart);
String fieldSwitches = fieldCode.replace(NUM_PAGES_FIELD_NAME, "").trim();
Node previousNode = fieldStart.getPreviousSibling();
if (previousNode == null)
previousNode = fieldStart;
builder.moveTo(previousNode);
Field newField = builder.insertField(MessageFormat.format(" {0} {1}{2} {3} ", PAGE_REF_FIELD_NAME, BOOKMARK_PREFIX, subDocumentCount, fieldSwitches));
previousNode.getParentNode().insertBefore(previousNode, newField.getStart());
removeField(fieldStart);
}
}
}
}
private static String getFieldCode(FieldStart fieldStart) throws Exception
{
StringBuilder builder = new StringBuilder();
for (Node node = fieldStart; node != null && node.getNodeType() != NodeType.FIELD_SEPARATOR &&
node.getNodeType() != NodeType.FIELD_END; node = node.nextPreOrder(node.getDocument()))
{
if (node.getNodeType() == NodeType.RUN)
builder.append(node.getText());
}
return builder.toString();
}
private static void removeField(FieldStart fieldStart) throws Exception
{
Node currentNode = fieldStart;
boolean isRemoving = true;
while (currentNode != null && isRemoving)
{
if (currentNode.getNodeType() == NodeType.FIELD_END)
isRemoving = false;
Node nextNode = currentNode.nextPreOrder(currentNode.getDocument());
currentNode.remove();
currentNode = nextNode;
}
}
Issue: Total page output.docx contains 12 and last page footer is showing page number as 12 of 11 which is wrong.
Note: Both the documents Identical1.docx and Identical2.docx are same and also contains same References.
Please suggest me any solution how to resolve the page number issue.

We have tested the scenario using latest version of Aspose.Words for Java 18.6 and have not found the shared issue. Please use Aspose.Words for Java 18.6. Please note that Aspose.Words mimics the behavior of MS Word. If you join these documents using MS Word, the final output document will have 9 pages.
Moreover, please share the code of AsposeUtil.convertNumPageFieldsToPageRef method for further testing.
I work with Aspose as Developer Evangelist.

Related

Bukkit Player check achievements

I don't know what I should put into player.getAdvancementProgress(Here).
if (player.getAdvancementProgress().isDone()) {
}
Maybe someone knows something?
You should use an Advancement object, specially the advancement that you are looking for informations.
You can get it with Bukkit.getAdvancement(NamespacedKey.fromString("advancement/name")) where advancement/name can be nether/all_potions for example. You can get all here (column: "Resource location). If you are getting it from command, I suggest you to add tab complete.
Example of TAB that show only not-done success :
#Override
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] arg) {
List<String> list = new ArrayList<>();
if(!(sender instanceof Player))
return list;
Player p = (Player) sender;
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT); // the begin of the searched advancement
Bukkit.advancementIterator().forEachRemaining((a) -> {
AdvancementProgress ap = p.getAdvancementProgress(a);
if((prefix.isEmpty() || a.getKey().getKey().toLowerCase().startsWith(prefix)) && !ap.isDone() && !a.getKey().getKey().startsWith("recipes"))
list.add(a.getKey().getKey());
});
return list;
}
Then, in the command you can do like that:
#Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] arg) {
if(!(sender instanceof Player)) // not allowed for no-player
return false;
Player p = (Player) sender;
// firstly: try to get advancement
Advancement a = Bukkit.getAdvancement(NamespacedKey.fromString(arg[0]));
if(a == null)
a = Bukkit.getAdvancement(NamespacedKey.minecraft(arg[0]));
if(a == null) // can't find it
p.sendMessage(ChatColor.RED + "Failed to find success " + arg[0]);
else { // founded :
AdvancementProgress ap = p.getAdvancementProgress(a);
p.sendMessage(ChatColor.GREEN + "Achivement " + a.getKey().getKey() + " stay: " + ChatColor.YELLOW + String.join(", ", ap.getRemainingCriteria().stream().map(this::getCleaned).collect(Collectors.toList())));
}
return false;
}
private String getCleaned(String s) { // this method is only to make content easier to read
String[] args = s.split("/");
return args[args.length - 1].replace(".png", "").replace(".jpg", "").replace("minecraft:", "").replace("_", " ");
}
Else, if you want to get all advancements, you should use Bukkit.advancementIterator().

Sitecore.Analytics.Tracker.Current is null when invoked through a pipeline

I need to redirect based on the country location the user is trying to access. For example when user trying to access http://www.example.com/ from china my site should as http://www.example.com/zh. I am checking using the sitecore tracker in pipeline process to get the country code using the below method.
public void Process(HttpRequestArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (HttpContext.Current == null
|| Context.Site == null
////TODO: || Sitecore.Context.PageMode...
|| Context.Database == null || Context.Site.Name == "shell" || !this._sites.Contains(Context.Site.Name))
{
return;
}
// contains path including language and query string
// (not anchor name), but not hostname.
// We can use this to add the language back into the path.
string rawPath = Sitecore.Context.RawUrl;
if (!rawPath.StartsWith("/sitecore") && !rawPath.StartsWith("/" + Sitecore.Context.Language.Name + "/") && !rawPath.StartsWith("/" + Sitecore.Context.Language.Name) && !rawPath.StartsWith("/default.aspx"))
{
string langCode = "";
if(!string.IsNullOrEmpty(GeoIPUtils.GetUserGeoIP()))
{
try
{
string country = GeoIPUtils.GetUserGeoIP();;
if (country.Trim().ToUpper() == "China".ToUpper())
langCode = "zh";
else if (country.Trim().ToUpper() == "Japan".ToUpper())
langCode = "jp";
else if (country.Trim().ToUpper() == "Thailand".ToUpper())
langCode = "th";
else
langCode = "en";
}
catch(Exception)
{
langCode = "en";
}
}
else
{
langCode = HttpContext.Current.Request.Cookies["avc#lang"].Value.ToString();
}
if (!string.IsNullOrEmpty(langCode))
{
Language language = null;
if (Language.TryParse(langCode, out language))
{
//then try to get the language item id from the language or two letter iso code
ID langID = LanguageManager.GetLanguageItemId(language, Sitecore.Context.Database);
if (!ID.IsNullOrEmpty(langID))
{
//sometimes the language found is slightly different than official language item used in SC
language = LanguageManager.GetLanguage(language.CultureInfo.TwoLetterISOLanguageName);
if (Context.Item != null)
{
List<string> availableLangs = LanguagesWithContent(Context.Item);
if (availableLangs != null && availableLangs.Count > 0 && !availableLangs.Contains(language.CultureInfo.TwoLetterISOLanguageName.ToString()))
{
langCode = availableLangs.FirstOrDefault().ToString();
}
}
else
{
langCode = "en";
}
}
else
{
langCode = "en";
}
}
}
HttpContext.Current.Response.RedirectPermanent("/" + (String.IsNullOrEmpty(langCode) ? Sitecore.Context.Language.Name : langCode) + rawPath);
}
}
Below is the GetUserGeoIP function
public static string GetUserGeoIP()
{
string countryCode = "";
try
{
countryCode = Sitecore.Analytics.Tracker.Current.Interaction.GeoData.Country;
}
catch(Exception ex)
{
Log.Error("GetUserGeoIP Error: " + ex.Message + " Source: " + ex.Source + " Stack Trace :" + ex.StackTrace + " Inner Ex : " + ex.InnerException, ex);
countryCode = "GB";
}
if (!string.IsNullOrEmpty(countryCode))
{
var countryItem = ISO3166.FromAlpha2(countryCode);
if (countryItem != null)
return countryItem.Name;
}
return "Other";
}
But I am getting an below exception
7904 10:43:25 ERROR Cannot create tracker.
Exception: System.InvalidOperationException
Message: session is not initialized
Source: Sitecore.Analytics
at Sitecore.Analytics.Data.HttpSessionContextManager.GetSession()
at Sitecore.Analytics.Pipelines.EnsureSessionContext.EnsureContext.Process(InitializeTrackerArgs args)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Analytics.DefaultTracker.EnsureSessionContext()
at Sitecore.Analytics.Pipelines.CreateTracker.GetTracker.Process(CreateTrackerArgs args)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Analytics.Tracker.Initialize()
Note: The same GetUserGeoIP method is used in API which gets the correct countryName. I am using Sitecore.NET 8.0 (rev. 151127) version
Any help on this highly appreciated
Your processor is probably too soon in the pipeline(s). You can find an overview of the request pipelines here: http://sitecoreskills.blogspot.be/2015/02/a-sitecore-8-request-from-beginning-to.html
You should put your processor after the tracker has been initialized and the geo data has been fetched. I did something similar a while ago and placed my processor in the startAnalytics pipeline.
Fetching the geo data is async so that might (will) give issues when doing this in the first request pipeline. Read this article to tackle that issue by calling UpdateGeoIpData with a timespan.

C# Get a drive's Name via it's Serial ID

I am using C# and working on Visual Studio 2015.
I need to get a Connected USB drive's name from it's Serial ID.
I tried using WMI Class the query: "SELECT * FROM Win32_LogicalDisk"
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");
foreach (ManagementObject item in searcher.Get())
{
if (item != null && item["VolumeSerialNumber"] != null && item["VolumeName"] != null)
{
if (item["VolumeSerialNumber"].ToString() == "50D76BF4")
{
Console.WriteLine($"{item["VolumeName"]} Is Connected and It's Letter is {item["Name"]}");
}
}
}
However, There VolumeSerialNumber is not ther real Serial ID. It is changed when the disk is formatted.
Ok I figured it out.
I wrote a method that reutrns a hard drive's name and letter from it's real and unchangable id.
You need to refernce System.Management
this is the code:
public static string GetDriveLetterAndLabelFromID(string id)
{
ManagementClass devs = new ManagementClass(#"Win32_Diskdrive");
{
ManagementObjectCollection moc = devs.GetInstances();
foreach (ManagementObject mo in moc)
{
string a = (string)mo["SerialNumber"];
if (a== id)
{
foreach (ManagementObject b in
mo.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementBaseObject c in b.GetRelated("Win32_LogicalDisk"))
{
string result = $"HardDrive Name: {c["VolumeName"].ToString()}\nHardDrive Letter: {c["DeviceID"]}";
return result;
}
}
}
}
}
return null;
}

MapReduce Hadoop - mapside joining the 2 data sets using customInputFormat

I am learning hadoop mapreduce framework ,i am trying to join 2 data sets have first record(Text) in the line as the Key , i tried to search in stackoverflow previous posts but nothing worked out.Here i am trying to customize the InputFormat and trying to join with the ID which is first record in the each line of data set.
My input file1:
cdd8dde3-0349-4f0d-b97a-7ae84b687f9c,Esther,Garner,4071 Haven Lane,Okemos,MI
81a43486-07e1-4b92-b92b-03d0caa87b5f,Timothy,Duncan,753 Stadium Drive,Taunton,MA
File2 :
cdd8dde3-0349-4f0d-b97a-7ae84b687f9c,517-706-9565,EstherJGarner#teleworm.us,Waskepter38,noL2ieghie,MasterCard,5305687295670850
81a43486-07e1-4b92-b92b-03d0caa87b5f,508-307-3433,TimothyDDuncan#einrot.com,Conerse,Gif4Edeiba,MasterCard,5265896533330445
**Driver class:**
conf.setInputFormat(CompositeInputFormat.class);
String strJoinStmt = CompositeInputFormat.compose("inner",
KeyValueLongInputFormat.class, dirEmployeesData, dirSalaryData);
conf.set("mapred.join.expr", strJoinStmt);
conf.setNumReduceTasks(0);
dirOutput.getFileSystem(conf).delete(dirOutput);
TextOutputFormat.setOutputPath(conf, dirOutput);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(Text.class);
conf.setOutputFormat(TextOutputFormat.class);
**Custom RecordReader class:**
public class KeyValueLongLineRecordReader implements
RecordReader<Text, Text> {
private final LineRecordReader lineRecordReader;
private byte separator = (byte) ',';
private LongWritable dummyKey;
private Text innerValue;
public Class getKeyClass() {
return Text.class;
}
public Text createKey() {
return new Text("");
}
public Text createValue() {
return new Text();
}
public KeyValueLongLineRecordReader(Configuration job, FileSplit split)
throws IOException {
lineRecordReader = new LineRecordReader(job, split);
dummyKey = lineRecordReader.createKey();
innerValue = lineRecordReader.createValue();
String sepStr = job.get("key.value.separator.in.input.line", ",");
this.separator = (byte) sepStr.charAt(0);
}
public static int findSeparator(byte[] utf, int start, int length, byte sep) {
for (int i = start; i < (start + length); i++) {
if (utf[i] == sep) {
return i;
}
}
return -1;
}
/** Read key/value pair in a line. */
public synchronized boolean next(Text key, Text value)
throws IOException {
Text tKey = key;
Text tValue = value;
byte[] line = null;
int lineLen = -1;
if (!lineRecordReader.next(dummyKey, innerValue)) {
return false;
}
else
line = innerValue.getBytes();
lineLen = innerValue.getLength();
if (line == null)
return false;
int pos = findSeparator(line, 0, lineLen, this.separator);
if (pos == -1) {
tKey.set(new String(line, 0, lineLen));
tValue.set("");
} else {
int keyLen = pos;
byte[] keyBytes = new byte[keyLen];
System.arraycopy(line, 0, keyBytes, 0, keyLen);
int valLen = lineLen - keyLen - 1;
byte[] valBytes = new byte[valLen];
System.arraycopy(line, pos + 1, valBytes, 0, valLen);
tKey.set(new String(keyBytes));
tValue.set(valBytes);
}
return true;
}
}
**InputFormat class:**
public class KeyValueLongInputFormat extends
FileInputFormat<Text, Text> implements JobConfigurable {
private CompressionCodecFactory compressionCodecs = null;
#Override
public void configure(JobConf conf) {
compressionCodecs = new CompressionCodecFactory(conf);
}
protected boolean isSplitable(FileSystem fs, Path file) {
return compressionCodecs.getCodec(file) == null;
}
#Override
public RecordReader<Text, Text> getRecordReader(
InputSplit genericSplit, JobConf job, Reporter reporter)
throws IOException {
reporter.setStatus(genericSplit.toString());
return new KeyValueLongLineRecordReader(job, (FileSplit) genericSplit);
}
}
**Finally Mapper class:**
enter code here
public class MapperMapSideJoinLargeDatasets extends MapReduceBase implements
Mapper<Text, TupleWritable, Text, Text> {
Text txtKey = new Text("");
Text txtValue = new Text("");
#Override
public void map(Text key, TupleWritable value,
OutputCollector<Text, Text> output, Reporter reporter)
throws IOException {
if (value.toString().length() > 0) {
txtKey.set(key.toString());
String arrEmpAttributes[] = value.get(0).toString().split(",");
String arrDeptAttributes[] = value.get(1).toString().split(",");
txtValue.set(arrEmpAttributes[1].toString() + "\t"
+ arrEmpAttributes[2].toString() + "\t"
+ arrDeptAttributes[0].toString());
output.collect(txtKey, txtValue);
}
}
In the logs Map input records is 0.No output can be seen on hdfs .Someone please help me to understand this issue. Thanks
The problem lies in the Driver class where in InputFormat mentioned as KeyValueLongInputFormat.class in the strJoinStmt property which actually works for LongWritable key and Text value. Instead KeyValueTextInputFormat.class can be used when both the key and value are of Text type.As the input is comma separated file, also specify a custom delimiter as comma by setting a property in the job's configuration object as follows in the Driver class.conf.set("key.value.separator.in.input.line",",");
For Complete details please check the below example:
https://github.com/sudha-pn/CompositeInputFormat

entity framework 6.1 duplicate unique index exception handling

How can I handle duplicate key row with unique index SqlException using [Index(IsUnique = true)] attribute in entity framework 6.1?
So here is a quick hack
try
{
context.SaveChanges();
}
catch (DbUpdateException e)
{
SqlException innerException = null;
Exception tmp = e;
while(innerException == null && tmp!=null)
{
if (tmp != null)
{
innerException = tmp.InnerException as SqlException;
tmp = tmp.InnerException;
}
}
if (innerException != null && innerException.Number == 2601)
{
// handle exception
}
else
{
throw;
}
}
I hope there is a better solution...
You can override the ValidateEntity in your dbContext and do your logic here.
I've posted about generic way how to do it in CodeProject
Validate a Unique Constraint at dbContext ValidateEntity in Entity Framework